home *** CD-ROM | disk | FTP | other *** search
/ Aminet 19 / Aminet 19 (1997)(GTI - Schatztruhe)[!][Jun 1997].iso / Aminet / comm / news / DWdecode.lha / dwdecode1.02 / DWdecode < prev    next >
Text File  |  1997-04-01  |  167KB  |  3,965 lines

  1. /**************************************************************************/
  2. /*                                                                        */
  3. /*                             DWDecode v1.02                             */
  4. /*                                                                        */
  5. /*                                                                        */
  6. /*                  Copyright ©1996-1997 by Dick Whiting                  */
  7. /*                                                                        */
  8. /*========================================================================*/
  9. /*                                                                        */
  10. /*                                                                        */
  11. /* Report bugs, comments, etc. to:                                        */
  12. /*                                                                        */
  13. /*                   Dick Whiting <dwhiting@europa.com>                   */
  14. /*                                                                        */
  15. /*                            01 April 1997                               */
  16. /*                                                                        */
  17. /**************************************************************************/
  18.  
  19. /* 
  20. $VER: DWDecode v1.02 Copyright ©1996-97 by Dick Whiting  
  21. */
  22.  
  23. Parse arg commandline                    /* get command line options      */
  24.  
  25. options failat 21                        /* block rc<21 from sending msgs */
  26. options results                          /* enable return codes           */
  27.  
  28. SIGNAL ON IOERR
  29. SIGNAL ON SYNTAX
  30.  
  31. Call Init                                /* initialize tables, vars, etc. */
  32.  
  33. Do dirptr=1 to dirlist.0                 /* loop thru all directories     */
  34.    Call BldFileNote                      /* Create filenotes for this dir */
  35.    Call ScanFiles                        /* Scan for key strings          */
  36.    Call ReadUnknowns                     /* Check files w/o encode set    */
  37.    Call Phase2                           /* complete info in Files array  */
  38.    Call ReportFiles                      /* generate file by file report  */
  39.    Call IssueWarnings                    /* issue warnings - none so far  */
  40.    Call FileNoteInFiles                  /* filenote inputs-encode & subj */
  41.    Call BuildLists                       /* build array for decoding use  */   
  42.    Call DecodeFiles                      /* do the actual decoding        */ 
  43.    Call DoOldFiles                       /* handle Delete/Mark old files  */
  44.    Call ListStats                        /* report time & cnts for dir    */
  45.    Call DumpArrays                       /* dump arrays for this dir      */   
  46.    if verbose then do
  47.       say time() 'Done processing 'dirlist.dirptr
  48.       say ' '
  49.    end
  50. end 
  51.  
  52. Cleanup:
  53.  
  54. if exists(DWtemp'DWdecode.scan') then do /* delete the scan file          */
  55.    Address Command 'Delete 'DWtemp'DWdecode.scan QUIET'
  56. end
  57.  
  58. if exists(DWtemp'DWdecode.temp') then do /* delete the join temporary file*/
  59.    Address Command 'Delete 'DWtemp'DWdecode.temp QUIET'
  60. end
  61.  
  62. Address Command 'Assign ' DWassignIN     /* remove the DW assign          */
  63.  
  64. pragma('D',origdir)                      /* reset to original directory   */
  65.  
  66. exit
  67.  
  68. /**************************************************************************/
  69. /*                                                                        */
  70. /*          Build the filenote string as requested in FILENOTE=var        */
  71. /*                                                                        */
  72. /*      Variable fnote may contain variables for later interpretation.    */
  73. /*                                                                        */
  74. /**************************************************************************/
  75. BldFileNote:
  76.  
  77.    if Filenote~='' then do 
  78.       fnote=filenote
  79.       do j=words(filenote) to 1 by -1
  80.          select
  81.             when upper(word(filenote,j))='%SOURCE' then do
  82.                wptr=wordindex(filenote,j)-1
  83.                fnote=delword(fnote,j,1)
  84.                sdir="'"||'dirlist.dirptr'||"'"
  85.                fnote=insert(sdir,fnote,wptr,length(sdir)+1,' ')
  86.             end
  87.             when upper(substr(word(filenote,j),1,4))='%LLQ' then do
  88.                llqnum=substr(word(filenote,j),5)
  89.                if llqnum='' then llqnum=1
  90.                if ~datatype(llqnum,'N') then llqnum=99
  91.                if llqnum<1 then llqnum=99
  92.                llq=translate(dirlist.dirptr,'  ',':/')
  93.                if llqnum>words(llq) then llqnum=words(llq)
  94.                llq=subword(llq,words(llq)-llqnum+1) 
  95.                wptr=wordindex(filenote,j)-1
  96.                fnote=delword(fnote,j,1)
  97.                fnote=insert(llq,fnote,wptr,length(llq)+1,' ')
  98.             end
  99.             when upper(substr(word(filenote,j),1,4))='%HLQ' then do
  100.                hlqnum=substr(word(filenote,j),5)
  101.                if hlqnum='' then hlqnum=1
  102.                if ~datatype(hlqnum,'N') then hlqnum=1 
  103.                if hlqnum<1 then hlqnum=1 
  104.                hlq=translate(dirlist.dirptr,'  ',':/')
  105.                if hlqnum>words(hlq) then hlqnum=words(hlq)
  106.                hlq=subword(hlq,1,hlqnum)             
  107.                wptr=wordindex(filenote,j)-1
  108.                fnote=delword(fnote,j,1)
  109.                fnote=insert(hlq,fnote,wptr,length(hlq)+1,' ')
  110.             end
  111.             when upper(substr(word(filenote,j),1,5))='%QUAL' then do
  112.                qnum1=substr(word(filenote,j),6,1)
  113.                if qnum1='' then qnum1=1
  114.                if ~datatype(qnum1,'N') then qnum1=1
  115.                if qnum1<1 then qnum=1
  116.                qual=translate(dirlist.dirptr,'  ',':/')
  117.                if qnum1>words(qual) then qnum1=words(qual)
  118.                qnum2=substr(word(filenote,j),7,1)
  119.                if qnum2='' then qnum2=words(qual)
  120.                if ~datatype(qnum2,'N') then qnum2=words(qual)
  121.                if qnum2<1 then qnum=words(qual)
  122.                if qnum2>words(qual) then qnum2=words(qual)
  123.                qual=subword(qual,qnum1,qnum2) 
  124.                wptr=wordindex(filenote,j)-1
  125.                fnote=delword(fnote,j,1)
  126.                fnote=insert(qual,fnote,wptr,length(qual)+1,' ')
  127.             end
  128.             when upper(word(filenote,j))='%SUBJECT' then do
  129.                wptr=wordindex(filenote,j)-1
  130.                fnote=delword(fnote,j,1)
  131.                subj="'"||'Subjinfo.Filesptr.1.1'||"'"
  132.                fnote=insert(subj,fnote,wptr,length(subj)+1,' ')
  133.             end
  134.             when upper(word(filenote,j))='%DATE' then do
  135.                wptr=wordindex(filenote,j)-1
  136.                fnote=delword(fnote,j,1)
  137.                date="'"||'Dateinfo.Filesptr.1.1'||"'"
  138.                fnote=insert(date,fnote,wptr,length(date)+1,' ')
  139.             end
  140.             when upper(word(filenote,j))='%FROM' then do
  141.                wptr=wordindex(filenote,j)-1
  142.                fnote=delword(fnote,j,1)
  143.                from="'"||'Frominfo.Filesptr.1.1'||"'"
  144.                fnote=insert(from,fnote,wptr,length(from)+1,' ')
  145.             end
  146.             otherwise nop
  147.          end
  148.       end   
  149.       fnote=strip(fnote)                    /* remove extra blanks        */
  150.       fnote="'"||fnote||"'"                 /* enclose string in quotes   */
  151.    end   /* matches with filenote~='' */
  152.  
  153. Return
  154.  
  155. /**************************************************************************/
  156. /*                                                                        */
  157. /* Scan directory for key strings used for identifying encode type, part  */
  158. /* information and header information.                                    */
  159. /*                                                                        */
  160. /* !! Should allow for multiple search programs, but not sure of output   */
  161. /*    parsing handling. The command could be specified as a template.     */
  162. /*                                                                        */
  163. /**************************************************************************/
  164. /*                                                                        */
  165. /* Read the lines from the sorted scan array. Determine what kind of      */
  166. /* line it is and store appropriately for Date:, From:, and Subject:      */
  167. /*                                                                        */
  168. /* Look for valid Section and begin lines. Get whatever info possible.    */
  169. /* Look for valid Base64 indicators and store info as available.          */
  170. /*                                                                        */
  171. /* The next routine will try to handle completing any parts using the     */
  172. /* information in the subject lines.                                      */
  173. /*                                                                        */
  174. /* ASSUMPTIONS:                                                           */
  175. /*  1) If file has a valid Section or begin line then it is UUencoded.    */
  176. /*  2) If an 'end' line occurs after a begin, it is a 1/1 part.           */
  177. /*  3) If file has a valid Base64 line then the file is Base64 encoded.   */
  178. /*  4) If a nth Base64 marker occurs, assume previous one is complete.    */
  179. /*  5) Files with multiple encoded parts are 1/1 files                    */
  180. /*                                                                        */
  181. /*========================================================================*/
  182. /*                          ARRAY FORMATS                                 */
  183. /*========================================================================*/
  184. /*               (0)=cnt             (0)=cnt                              */
  185. /* Files. format: filename.encodetype.partname.partnum.parttot.startline  */
  186. /*                        .encodetype.partname.partnum.parttot.startline  */
  187. /*                                                                        */
  188. /*                                     (Y/N/.)  (Y/.)     (Y/.)  (Y/.)    */
  189. /* Miscinfo. format: filename.mimetype.decoded.filenoted.chopped.dupfile  */
  190. /*                                                                        */
  191. /*                    (0)=cnt                                             */
  192. /* Subjinfo. format: skipflag.deleteflag.textline                         */
  193. /* Frominfo. format: skipflag.deleteflag.textline                         */
  194. /* Dateinfo. format: skipflag.deleteflag.textline                         */
  195. /*                                                                        */
  196. /*                                   (0)#partname matches in subject line */
  197. /*                                         (0)#partnums in subject line   */
  198. /*                                                    (0)#totals in sub   */
  199. /*                   Files                  spart      spart              */
  200. /* Partone.  format: Pointer.partname.sword.number.loc.total.loc.subjline */
  201. /*                                                                        */
  202. /* Partxxx.=same format as Partone.                                       */
  203. /*                                                                        */
  204. /**************************************************************************/
  205. ScanFiles:
  206.  
  207.    starttm=time('S')          /* start time for processing this directory */
  208.  
  209.    Address Command 'Assign ' DWassignIN dirlist.dirptr /*for shorter lines*/ 
  210.  
  211.    ScanArray.=missing          /* stores parsed information from scan prg */
  212.    ScanArray.0=0                                 /* no scan lines yet     */
  213.  
  214.    Files.=missing              /* stores information for each news file   */
  215.    Files.0=0                                     /* no File info yet      */
  216.  
  217.    Miscinfo. =missing          /* stores additional info for file/parts   */
  218.    Miscinfo.0=0                                  /* no Misc info yet      */
  219.  
  220.    Subjinfo. =missing                            /* init to missing       */
  221.    Subjinfo.0=0                                  /* no Subject lines yet  */
  222.  
  223.    Frominfo. =missing                            /* init to missing       */
  224.    Frominfo.0=0                                  /* no From    lines yet  */
  225.  
  226.    Dateinfo. =missing                            /* init to missing       */
  227.    Dateinfo.0=0                                  /* no Date    lines yet  */
  228.  
  229.    Partone. =missing                             /* init to missing       */
  230.    Partone.0=0                                   /* no partone  lines yet */
  231.    part1cnt=0                                    /* no partone  lines yet */
  232.  
  233.    Partxxx. =missing                             /* init to missing       */
  234.    Partxxx.0=0                                   /* no partxxx  lines yet */
  235.    partXcnt=0                                    /* no partxxx  lines yet */
  236.  
  237.    Parts.0=0                                     /* init to zero - report */
  238.    Temppart.0=0                                  /* init to zero - report */ 
  239.  
  240.    AllBegins.0=0                                 /* lines with begin      */
  241.    AllEncodes.0=0                                /* MIME encoding info    */
  242.    AllSections.0=0                               /* lines with section    */
  243.  
  244.    warnings.0=0                                  /* used for warning msgs */
  245.  
  246. if verbose then say time() 'Scanning ' dirlist.dirptr '...' 
  247.  
  248.    Address Command scanprog dirlist.dirptr 'From:    cs nh num  > ' DWtemp'DWdecode.scan'
  249.    Address Command scanprog dirlist.dirptr 'Subject: cs nh num >> ' DWtemp'DWdecode.scan'
  250.    Address Command scanprog dirlist.dirptr 'Date:    cs nh num >> ' DWtemp'DWdecode.scan'
  251.    Address Command scanprog dirlist.dirptr 'section     nh num >> ' DWtemp'DWdecode.scan'
  252.    Address Command scanprog dirlist.dirptr 'begin    cs nh num >> ' DWtemp'DWdecode.scan'
  253.    Address Command scanprog dirlist.dirptr 'end      cs nh num >> ' DWtemp'DWdecode.scan'
  254.    Address Command scanprog dirlist.dirptr 'Content- cs nh num >> ' DWtemp'DWdecode.scan'
  255.    Address Command scanprog dirlist.dirptr 'number=  cs nh num >> ' DWtemp'DWdecode.scan'
  256.    do i=1 to Base64Types.0
  257.       Address Command scanprog dirlist.dirptr Base64Types.i ' cs nh num >> ' DWtemp'DWdecode.scan'
  258.    end
  259.  
  260. if verbose then say time() 'Reading the scan file ...'
  261.  
  262.    goodopen=open('IN',DWtemp'DWdecode.scan','R')
  263.    if ~goodopen then do
  264.       msg='(E) Error in opening ' DWtemp'DWdecode.scan'
  265.       interpret Saycmd
  266.       msg='    No further processing for this directory possible'
  267.       interpret Saycmd
  268.       exit
  269.    end
  270.    dirname=dirlist.dirptr                        /* name of directory     */
  271.    device=substr(dirname,1,pos(':',dirname))     /* get device portion    */
  272.    directs=substr(dirname,pos(':',dirname)+1)    /* remaining portion     */
  273.    if upper(device)='RAM:' then dirname='Ram Disk:'||directs  /* fix Ram: */
  274.    dirlen=length(dirname)                        /* length of dir name    */
  275.    filename=missing                              /* init to missing       */
  276.    sptr=0                                        /* scanarray pointer     */
  277.  
  278.    do until eof('IN')
  279.       linein=readln('IN')
  280.       select
  281.          when pos(dirname,linein)=1 & word(linein,words(linein))='...' then do
  282.             fullname=subword(linein,1,words(linein)-1) /* name with path  */
  283.             filename=substr(fullname,dirlen+1)   /* just the filename part*/
  284.             if pos('/',filename)>0 then do 
  285.                filename=substr(filename,lastpos('/',filename)+1)
  286.             end
  287.          end
  288.          when words(linein)=2 & word(linein,2)='...' then do
  289.             fullname=word(linein,1)              /* filename with path    */
  290.             filename=substr(fullname,dirlen+1)   /* just the filename part*/
  291.             if pos('/',filename)>0 then do 
  292.                filename=substr(filename,lastpos('/',filename)+1)
  293.             end
  294.          end
  295.          when words(linein) > 0 then do
  296.             linenum=strip(word(linein,1))        /* line number found     */
  297.             linenum=right(linenum,6,'0')         /* put in leading zeros  */
  298.             text=subword(linein,2)               /* remaining string      */
  299.             select 
  300.                when word(text,1)='Newsgroups:' then nop
  301.                when word(text,1)='Xref:' then nop
  302.                when substr(word(text,1),1,2)='X-' then nop
  303.                when word(text,1)='Content-Description:' then nop
  304.                otherwise do
  305.                   sptr=sptr+1                          /* increment cnter */
  306.                   scanarray.0=sptr                     /* store it        */    
  307.                   scanarray.sptr=filename linenum text /* put it in array */   
  308.                end
  309.             end
  310.          end
  311.          otherwise nop /* should be end of file */
  312.       end
  313.    end
  314.  
  315.    result=close('IN')                            /* close the scan file   */
  316.  
  317. if verbose then say time() 'Sorting the scan array ...'
  318.  
  319.    if show('L','rexxtricks.library') then do    /* use tricks library     */
  320.       call QSORT(scanarray)                  /* sort by name, line number */
  321.    end
  322.    else do                                   /* use QuickSort format      */
  323.       call QSORT(1,scanarray.0,scanarray)    /* sort by name, line number */
  324.    end 
  325.  
  326.    if DEBUG=YES then do 
  327.       msg=' '
  328.       interpret Saycmd
  329.       msg='Dumping ScanArray ...'
  330.       interpret Saycmd
  331.       msg=left(dashes,length(msg))
  332.       interpret Saycmd
  333.       do i=1 to scanarray.0                          /* for debugging     */ 
  334.          msg=scanarray.i
  335.          interpret Saycmd
  336.       end
  337.       msg=' '
  338.       interpret Saycmd
  339.    end
  340.  
  341.    SkipSubjCnt=0                                 /* used for reporting    */
  342.    SkipFromCnt=0                                 /* used for reporting    */ 
  343.    B64OutCnt=0                                   /* used for reporting    */
  344.    UUOutCnt=0                                    /* used for reporting    */
  345.    BinOutCnt=0                                   /* used for reporting    */
  346.  
  347.    oldfile=missing                               /* break control on file */
  348.    oldsection=missing                            /* used to trap end sect.*/
  349.    fptr=0                                        /* files array pointer   */
  350.  
  351.    partname=missing                              /* no partname yet       */
  352.    partnum=missing                               /* no partnum yet        */
  353.    parttot=missing                               /* no part total yet     */ 
  354.    partlin=missing                               /* decode start line num */
  355.    pptr=0                                        /* zero to start with    */
  356.    encode=missing                                /* init to missing       */ 
  357.    beginfound=NO                                 /* no begins found yet   */
  358.    CCdata=NO                                     /* NO Content data yet   */
  359.  
  360. if verbose then say time() 'Processing the scan array ...'
  361.  
  362.    do i=1 to scanarray.0
  363.       filename=word(scanarray.i,1)               /* filename in array     */
  364.       linenum=word(scanarray.i,2)                /* line number in array  */       
  365.       text=subword(scanarray.i,3)                /* remainder of line     */
  366.       text=translate(text,' ',cr)                /* remove PC Ctrl-M      */ 
  367.       if filename~=oldfile then do               /* got a level break     */
  368.          if encode~=missing then Call StorePartVars /* do previous part   */
  369.          if oldfile~=missing then do 
  370.             skipflag=NO                          /* didn't do any skips   */
  371.             Call CheckSkips                      /* handle Skip/Deletes   */
  372.             if skipflag=YES then do              /* clear array entries   */
  373.                Files.fptr.1=missing              /* clear encode value    */
  374.                Frominfo.fptr.1.1=missing
  375.                Subjinfo.fptr.1.1=missing
  376.                Dateinfo.fptr.1.1=missing
  377.                encode=missing                    /* clear control vars    */
  378.                fptr=fptr-1                       /* reuse current slot    */ 
  379.                pptr=0                            /* clear control vars    */
  380.             end 
  381.          end
  382.          oldfile=filename                        /* copy for next break   */
  383.          fptr=fptr+1                             /* next files. pointer   */
  384.          Files.0=fptr                            /* count the file        */
  385.          Files.fptr=filename                     /* store filename        */
  386.          Files.fptr.1.0=0                        /* no parts yet          */
  387.          Dateinfo.fptr=0                         /* don't skip            */
  388.          Dateinfo.fptr.1=0                       /* don't delete          */
  389.          Frominfo.fptr=0                         /* don't skip            */
  390.          Frominfo.fptr.1=0                       /* don't delete          */
  391.          Subjinfo.fptr=0                         /* don't skip            */
  392.          Subjinfo.fptr.1=0                       /* don't delete          */
  393.          pptr=0                                  /* partname slot pointer */
  394.          Call ResetPartVars                      /* reset partname vars   */
  395.          oldsection=missing                      /* used to trap end sect.*/
  396.       end
  397.  
  398.       select
  399.          when word(text,1)='From:' & Frominfo.fptr.1.1=missing then do
  400.             text=translate(text,'  ','"`')       /* blank all type quotes */
  401.             text=translate(text,' ',"'")         /* blank all type quotes */
  402.             Frominfo.fptr.1.1=substr(text,7)     /* store From info       */
  403.          end
  404.          when word(text,1)='Subject:' & Subjinfo.fptr.1.1=missing then do
  405.             text=translate(text,'  ','"`')       /* blank all type quotes */
  406.             text=translate(text,' ',"'")         /* blank all type quotes */
  407.             Subjinfo.fptr.1.1=substr(text,10)    /* store Subject info    */
  408.          end
  409.          when word(text,1)='Date:' & Dateinfo.fptr.1.1=missing then do
  410.               Dateinfo.fptr.1.1=substr(text,7)
  411.          end
  412.          when pos('SECTION',upper(word(text,1)))>0 then do
  413.             Call CheckSections
  414.             Call StorePartVars                /* complete set - store  */
  415.          end
  416.          when substr(text,1,6)='begin ' & datatype(word(text,2),'N') then do 
  417.             partnum=1                            /* begins are part ones  */
  418.             bpname=strip(subword(text,3))        /* get partname portion  */
  419.             if partname~=bpname then do          /* didn't have a section */
  420.                partname=bpname                   /* begin line partname   */ 
  421.                encode='UU'                       /* encode type           */
  422.                partlin=linenum            /* good starting point in file  */
  423.                Call StorePartVars                /* complete set - store  */
  424.             end
  425.             beginfound=YES                       /* indicator for 'end '  */ 
  426.          end
  427.          when word(text,1)='end' & encode='UU' & beginfound=YES then do
  428.             parttot=1                            /* !! total - unused ?   */
  429.             Call StorePartVars                   /* store what we've got  */
  430.             Call ResetPartVars                   /* reset partname vars   */
  431.          end
  432.          when pos('Content-',word(text,1))=1 then do
  433.             Call CheckContent
  434.             if CCdata=YES & Ctype>1 & encode ~=missing then do
  435.                Call StorePartVars                /* store what we've got  */
  436.                Call ResetPartVars                /* reset partname vars   */
  437.             end
  438.          end
  439.          otherwise do
  440.             if encode=missing then do            /* not from a Content-   */
  441.                Call CheckBase64                  /* non-MIME B64 encoding */ 
  442.                if encode='64' then do            /* found a B64 start str */
  443.                   partnum=1                      /* begins are part ones  */
  444.                   encode='64'                    /* encode type           */
  445.                   Call StorePartVars             /* store what we've got  */
  446.                   Call ResetPartVars             /* reset partname vars   */
  447.                end
  448.             end
  449.          end
  450.       end
  451.    end                                  /* matches do i=1 to scanarray.0  */
  452.  
  453.    skipflag=NO                                   /* NO skips yet          */
  454.    Call CheckSkips                               /* check LAST file       */
  455.    if skipflag=YES then fptr=fptr-1              /* don't count last one  */
  456.    if encode~=missing & skipflag=NO then Call StorePartVars /*last part   */
  457.    
  458.    Files.0=fptr                                  /* count of files found  */
  459.    Frominfo.0=fptr                               /* count of files found  */
  460.    Subjinfo.0=fptr                               /* count of files found  */
  461.    Dateinfo.0=fptr                               /* count of files found  */
  462.    Miscinfo.0=fptr                               /* count of files found  */
  463.  
  464. ScanFilesEnd:
  465.  
  466. Return
  467.  
  468. /**************************************************************************/
  469. /*  Check for Skip/Delete based on Subject: or From: lines. If SKIP then  */
  470. /*  filenote the file and reuse Files. slot. If DELETE then delete the    */
  471. /*  file and reuse the slot. Skipped/Deleted will not appear on any rpts  */
  472. /*  or be included in the match logic phases.                             */
  473. /*                                                                        */
  474. /*  Date deletes will be flagged for handling after the Decoding.         */
  475. /**************************************************************************/
  476. DoOldFiles:
  477.  
  478.    If MarkOld | DeleteOld then do
  479.       do fptr=1 to Files.0
  480.          if ~exists(DWassignIN||Files.fptr) then iterate fptr /* gone     */
  481.          if DeleteOld & ~ScanOnly then do
  482.             if Dateinfo.fptr.1=YES then do
  483.                Address Command 'Delete' DWassignIN||Files.fptr 'QUIET'
  484.             end
  485.          end
  486.          else do
  487.             if Dateinfo.fptr.1=YES then do
  488.                fnsubj=Subjinfo.fptr.1.1          /* subject for filenote  */
  489.                fnsubj=substr(fnsubj,1,75)        /* shorten to max length */ 
  490.                if Files.fptr.1=missing then fnsubj='O   '||fnsubj
  491.                                        else fnsubj='O'||Files.fptr.1||' '||fnsubj
  492.                filein=DWassignIN||Files.fptr
  493.                Address Command 'Filenote 'filein '"'fnsubj'" ' 
  494.             end
  495.          end
  496.       end
  497.    end
  498.  
  499. Return
  500.  
  501. /**************************************************************************/
  502. /*                                                                        */
  503. /*           Report counts and time information for this directory        */
  504. /*                                                                        */
  505. /**************************************************************************/
  506. ListStats:
  507.  
  508.    if ShowStats then do 
  509.       totfiles=SkipSubjCnt+SkipFromCnt+Files.0
  510.       if totfiles=0 then signal ListStatsEnd
  511.       maxval=max(Files.0,Parts.0,Temppart.0,totfiles)
  512.       rlen=length(maxval)
  513.       msg=' ' 
  514.       interpret saycmd
  515.       msg=right(totfiles,rlen) 'File(s) in 'dirlist.dirptr
  516.       interpret saycmd
  517.       msg=right(SkipSubjCnt,rlen) 'File(s) skipped/deleted due to Subject: matches'
  518.       interpret saycmd
  519.       msg=right(SkipFromCnt,rlen) 'File(s) skipped/deleted due to From: matches'
  520.       interpret saycmd
  521.       msg=right(Temppart.0,rlen) 'Encoded pieces completely identified'
  522.       interpret saycmd
  523.       complete=0
  524.       do j=1 to parts.0
  525.          if parts.j.1=parts.j.1.0 then complete=complete+1
  526.       end
  527.       msg=right(complete,rlen) 'Complete encoded files (excludes duplicates)'
  528.       interpret saycmd
  529.       msg=right(UUOutCnt,rlen) 'UU Encoded output files written'
  530.       interpret saycmd
  531.       msg=right(B64OutCnt,rlen) 'Base64 Encoded output files written'
  532.       interpret saycmd
  533.       msg=right(BinOutCnt,rlen) 'BinHex Encoded output files written'
  534.       interpret saycmd
  535.  
  536.       endtm=time('S')   
  537.       elapstm=endtm-starttm
  538.       hh=elapstm%3600
  539.       hh=right(hh,2,'0')
  540.       elapstm=elapstm-(3600*hh)
  541.       mm=elapstm%60
  542.       mm=right(mm,2,'0')
  543.       ss=elapstm-(60*mm)
  544.       ss=right(ss,2,'0')
  545.       msg=copies(' ',rlen) 'Processing time for this directory:' hh':'mm':'ss 
  546.       interpret Saycmd
  547.    end
  548.  
  549. ListStatsEnd:
  550.  
  551. Return
  552.  
  553. /**************************************************************************/
  554. /*  Check for Skip/Delete based on Subject: or From: lines. If SKIP then  */
  555. /*  filenote the file and reuse Files. slot. If DELETE then delete the    */
  556. /*  file and reuse the slot. Skipped/Deleted will not appear on any rpts  */
  557. /*  or be included in the match logic phases.                             */
  558. /*                                                                        */
  559. /*  Date deletes will be flagged for handling after the Decoding.         */
  560. /**************************************************************************/
  561. CheckSkips:
  562.  
  563.    If SkipFrom | DeleteFrom then do
  564.       do skipcnt=1 to SkipFroms.0
  565.          if pos(upper(SkipFroms.skipcnt),upper(Frominfo.fptr.1.1))>0 then do
  566.             if DeleteFrom & ~ScanOnly then do 
  567.                Address Command 'Delete' DWassignIN||Files.fptr 'QUIET'
  568.             end
  569.             else do
  570.                fnsubj=Subjinfo.fptr.1.1                   /* subject for filenote  */
  571.                fnsubj=substr(fnsubj,1,75)                 /* shorten to max length */ 
  572.                if Files.fptr.1=missing then fnsubj='F   '||fnsubj
  573.                                        else fnsubj='F'||Files.fptr.1||' '||fnsubj
  574.                filein=DWassignIN||Files.fptr
  575.                Address Command 'Filenote 'filein '"'fnsubj'" ' 
  576.             end
  577.             skipflag=YES
  578.             SkipFromCnt=SkipFromCnt+1
  579.             leave skipcnt         
  580.          end
  581.       end 
  582.    end
  583.    
  584.    If SkipSubject | DeleteSubject then do
  585.       do skipcnt=1 to SkipSubjects.0
  586.          if pos(upper(SkipSubjects.skipcnt),upper(Subjinfo.fptr.1.1))>0 then do
  587.             if DeleteSubject & ~ScanOnly then do
  588.                if exists(DWassignIN||Files.fptr) then do
  589.                   Address Command 'Delete' DWassignIN||Files.fptr 'QUIET'
  590.                end
  591.             end 
  592.             else do
  593.                fnsubj=Subjinfo.fptr.1.1                   /* subject for filenote  */
  594.                fnsubj=substr(fnsubj,1,75)                 /* shorten to max length */ 
  595.                if Files.fptr.1=missing then fnsubj='S   '||fnsubj
  596.                                        else fnsubj='S'||Files.fptr.1||' '||fnsubj
  597.                filein=DWassignIN||Files.fptr
  598.                if ~skipflag then Address Command 'Filenote 'filein '"'fnsubj'" ' 
  599.             end
  600.             if ~skipflag then do
  601.                skipflag=YES
  602.                SkipSubjCnt=SkipSubjCnt+1
  603.             end 
  604.             leave skipcnt         
  605.          end
  606.       end 
  607.    end
  608.    
  609.    If (MarkOld | DeleteOld) & Dateinfo.fptr.1.1~=missing  then do
  610.       datemsg=Dateinfo.fptr.1.1
  611.       Call TimeStamp
  612.       if (today-days)>KeepDays then do
  613.          Dateinfo.fptr.1=YES
  614.       end 
  615.    end
  616.  
  617. Return
  618.  
  619. /**************************************************************************/
  620. /*  Attach a filenote to each of the input files with encode & subject    */
  621. /*  This is the time to DELETE non-binaries if requested to.              */
  622. /**************************************************************************/
  623. FileNoteInFiles:
  624.  
  625. msg='Filenoting input files '
  626. if DeleteText then msg=msg||'and Deleting Text files '
  627. msg=msg||'...'
  628. if verbose then say time() msg
  629.  
  630. do i=1 to Files.0
  631.    filein=DWassignIN||Files.i                    /* name of file w/path   */
  632.    if DeleteText & Files.i.1=missing then do     /* a 'text' file         */
  633.       Address Command 'Delete ' filein ' QUIET'
  634.       iterate i                                  /* go onto next file     */
  635.    end
  636.    fnsubj=Subjinfo.i.1.1                         /* subject for filenote  */
  637.    fnsubj=substr(fnsubj,1,75)                    /* shorten to max length */ 
  638.    select
  639.       when Files.i.1=missing then do
  640.          encoding='Not an encoded file'
  641.          Address Command 'Filenote 'filein '"    '||fnsubj||'" '
  642.          fnrc=rc
  643.       end
  644.       when Files.i.1='UU' then do
  645.          encoding='UUencode'
  646.          Address Command 'Filenote 'filein '" UU '||fnsubj||'" ' 
  647.          fnrc=rc
  648.       end
  649.       when Files.i.1='64' then do
  650.          encoding='Base64'
  651.          Address Command 'Filenote  'filein '" 64 '||fnsubj||'" ' 
  652.          fnrc=rc
  653.       end
  654.       when Files.i.1='BH' then do
  655.          encoding='BinHex'
  656.          Address Command 'Filenote  'filein '" BH '||fnsubj||'" ' 
  657.          fnrc=rc
  658.       end
  659.       otherwise nop
  660.    end
  661.    if fnrc>0 then do
  662.       say 'Filenote returned RC='fnrc 'for 'filein
  663.       say 'Subject: 'fnsubj
  664.    end
  665. end
  666.  
  667. Return
  668.  
  669. /**************************************************************************/
  670. /*                                                                        */
  671. /*      Reset variables used to identify partnames, number, etc.          */
  672. /*                                                                        */
  673. /**************************************************************************/
  674. ResetPartVars:
  675.  
  676.    if pptr>1 then do                             /* an nth encode in file */
  677.       prev=pptr-1                                /* point to prev part    */
  678.       Files.fptr.1.prev.1.1=1                    /* must be a part 1/1    */
  679.    end
  680.    
  681.    if encode~=missing then Files.fptr.1.0=pptr   /* store partname cnt    */ 
  682.    partname=missing                              /* no partname yet       */
  683.    partnum=missing                               /* no partnum yet        */
  684.    parttot=missing                               /* no part total yet     */ 
  685.    partlin=missing                               /* decode start line num */
  686.    encode=missing                                /* null for encoding     */
  687.    pptr=pptr+1                                   /* NEXT part for filename*/
  688.    beginfound=NO                                 /* no begins found yet   */
  689.    CCdata=NO                                     /* NO Content data yet   */
  690.    Ctype=0                                       /* no Content-type yet   */
  691.  
  692. Return
  693.  
  694. /**************************************************************************/
  695. /*                                                                        */
  696. /*      Store variables used to identify partnames, number, etc.          */
  697. /*                                                                        */
  698. /**************************************************************************/
  699. StorePartVars:
  700.  
  701.    if encode~=missing   then do
  702.       Files.fptr.1.0=pptr
  703.       Files.fptr.pptr=encode 
  704.    end
  705.    if partname~=missing then do
  706.       Files.fptr.1.pptr=partname 
  707.    end
  708.    if partnum~=missing  then do
  709.       Files.fptr.1.pptr.1=partnum 
  710.    end
  711.    if parttot~=missing  then do
  712.       Files.fptr.1.pptr.1.1=parttot 
  713.    end
  714.    if partlin~=missing  then do
  715.       Files.fptr.1.pptr.1.1.1=partlin 
  716.    end
  717.  
  718. Return
  719.  
  720. /**************************************************************************/
  721. /*                                                                        */
  722. /*      See if this one has Section information (we hope so)              */
  723. /*                                                                        */
  724. /**************************************************************************/
  725. CheckSections:
  726.  
  727.    if text=oldsection then signal CheckSectionsEnd  /* a closing section  */
  728.  
  729.    if pos('SECTION',upper(text))>0 & TrapAllSecs then do
  730.       AllSections.0=1+AllSections.0
  731.       secptr=AllSections.0
  732.       AllSections.secptr=filename':'text
  733.    end
  734.  
  735.    do k=1 to sectiontypes.0               /* loop thru various forms      */
  736.       matchctr=0                          /* zero matches at start        */
  737.       do l=1 to sectiontypes.k            /* number of keys to test       */
  738.          key1=sectiontypes.k.l            /* primary search key           */
  739.          key1loc=sectiontypes.k.l.l       /* location of primary key      */
  740.          if word(text,key1loc)=key1 then matchctr=matchctr+1
  741.          else iterate k                   /* on any mismatch quit loop    */
  742.       end
  743.       if matchctr =sectiontypes.k then do        /* found a KNOWN section */
  744.          wpartnum =sectiontypes.k.1.1.1          /* word holding partnum  */
  745.          wparttot =sectiontypes.k.1.1.1.1        /* word holding total    */
  746.          wpartname=sectiontypes.k.1.1.1.1.1      /* name of file          */
  747.          partsep  =sectiontypes.k.1.1.1.1.1.1    /* delimiter char        */
  748.          if wpartnum=wparttot & wpartnum~=missing then do
  749.             partword=word(text,wpartnum)         /* get the word          */
  750.             partnum=substr(partword,1,pos(partsep,partword)-1)
  751.             parttot=substr(partword,pos(partsep,partword)+1)
  752.          end
  753.          else do
  754.             if wpartnum~=missing then partnum=word(text,wpartnum)
  755.             if wparttot~=missing then parttot=word(text,wparttot)
  756.          end
  757.          if wpartname~=missing then partname=word(text,wpartname)
  758.          if ~datatype(partnum,'N') then partnum=missing
  759.          if ~datatype(parttot,'N') then parttot=missing
  760.          encode='UU'                      /* Sections mean UU encoding    */ 
  761.          partlin=linenum                  /* good starting point in file  */
  762.          oldsection=text                  /* use to trap ending section   */
  763.          leave k              /* got everything we could from the SECTION */       
  764.       end  /* if matchctr=sectiontypes.k */
  765.       else do 
  766.          /* !!! should not get here !!! */
  767.          say 'Should not be here--- Check Sections'
  768.       end
  769.    end  /* do k=1 to sectiontypes.0 */
  770.  
  771.    if pos('SECTION',upper(text))>0 then do    /* unknown section found    */
  772.       if TrapNewSecs=YES & k>sectiontypes.0 then do
  773.          if exists(TrapNewSecsFile) then mode='A'
  774.                                     else mode='W'
  775.          goodopen=open('TRAPSECS',TrapNewSecsFile,mode)
  776.          if ~goodopen then do
  777.             msg='(E) Unable to open TrapSecFile:'TrapNewSecsFile
  778.             interpret Saycmd
  779.             msg='    Setting TrapNewSecs=NO'
  780.             interpret Saycmd
  781.          end
  782.          result=writeln('TRAPSECS',text)
  783.          result=close('TRAPSECS')
  784.       end  /* matches if TrapNewSecs=YES */
  785.    end  /* matches unknown section */
  786.  
  787. CheckSectionsEnd:
  788.  
  789. Return
  790.  
  791. /**************************************************************************/
  792. /*                                                                        */
  793. /*                     Handle the Content- type lines                     */
  794. /*                                                                        */
  795. /**************************************************************************/
  796. CheckContent:
  797.  
  798.    Select
  799.       When word(text,1)='Content-Type:' & ,
  800.            CCdata=YES & Ctype>0 & encode~=missing then do
  801.          Ctype=Ctype+1
  802.          i=i-1                         /* redo this line next iteration*/
  803.       end
  804.       When word(text,1)='Content-Type:' then do 
  805.          Ctype=0                       /* any previous wasn't encoded  */
  806.          Call CheckCType
  807.       end
  808.       When word(text,1)='Content-Transfer-Encoding:' then do
  809.          Call CheckCEncoding
  810.       end
  811.            
  812.       When word(text,1)='Content-Disposition:' then do 
  813.          Call CheckCDisp
  814.       end
  815.       Otherwise nop
  816.    end
  817.    
  818. CheckContentEnd:
  819.  
  820. Return
  821.  
  822. /**************************************************************************/
  823. /*                                                                        */
  824. /*                     Handle Content-Type lines                          */
  825. /*                                                                        */
  826. /**************************************************************************/
  827. CheckCType:
  828.  
  829.    Select
  830.       when upper(word(text,2))='MULTIPART/MIXED;' then nop 
  831.       when upper(word(text,2))='MESSAGE/PARTIAL;' then do
  832.          Call NextCline
  833.          if substr(CCword1,1,7)='number=' & substr(CCword2,1,6)='total=' then do
  834.             Call CheckCNumber
  835.          end          
  836.          else do
  837.             if substr(CCword1,1,3)='id=' then do    /* a scan word in id  */ 
  838.                i=i+1                                /* skip over id line  */
  839.                Call NextCline
  840.                if substr(CCword1,1,7)='number=' & substr(CCword2,1,6)='total=' then do
  841.                   Call CheckCNumber
  842.                end          
  843.             end  
  844.          end
  845.       end   /* matches MESSAGE/PARTIAL */
  846.       otherwise do  /* all other content-types for now */
  847.          Ctype=Ctype+1                              /* count Content-type */
  848.          if pos('name=',word(text,3))=1 then do
  849.             partname=subword(text,3)
  850.             squote=pos('"',partname)
  851.             if squote>0 then do 
  852.                equote=lastpos('"',partname)-(squote+1)
  853.                partname=substr(partname,squote+1,equote)
  854.             end
  855.             else do
  856.                partname=strip(substr(partname,6)) 
  857.             end
  858.             CCdata=YES
  859.          end
  860.       end   /* matches otherwise other Content-Types */
  861.    end   /* matches Content-Type Select */
  862.  
  863. CheckCTypeEnd:
  864.  
  865. Return
  866.  
  867. /**************************************************************************/
  868. /*                                                                        */
  869. /*                     Point to next line in scanarray                    */
  870. /*                                                                        */
  871. /**************************************************************************/
  872. NextCline:    
  873.  
  874.    CCi=i+1                               /* temp pointer for next line   */
  875.    CCfile=word(scanarray.CCi,1)
  876.    CCtext=subword(scanarray.CCi,3)
  877.    CCtext=translate(CCtext,'  ',tab)
  878.    CCword1=strip(word(CCtext,1))
  879.    CCword2=strip(word(CCtext,2))
  880.  
  881. Return
  882.  
  883. /**************************************************************************/
  884. /*                                                                        */
  885. /*                     Handle number= for Partials                        */
  886. /*                                                                        */
  887. /**************************************************************************/
  888. CheckCNumber:
  889.  
  890.    partnum=substr(CCword1,8)
  891.    partnum=strip(translate(partnum,' ',';'))
  892.    parttot=substr(CCword2,7)
  893.    parttot=strip(translate(parttot,' ',';'))
  894.    i=CCi
  895.    CCdata=YES
  896.  
  897. Return
  898.  
  899. /**************************************************************************/
  900. /*                                                                        */
  901. /*                     Handle Content-Encoding lines                      */
  902. /*                                                                        */
  903. /**************************************************************************/
  904. CheckCEncoding:
  905.  
  906.    if TrapAllEncs then do
  907.       AllEncodes.0=1+AllEncodes.0
  908.       encptr=AllEncodes.0
  909.       AllEncodes.encptr=filename':'text
  910.    end
  911.  
  912.    do k=1 to EncTypes.0                   /* loop thru various forms      */
  913.       matchctr=0                          /* zero matches at start        */
  914.       if upper(word(text,2))=upper(EncTypes.k) then do
  915.          matchctr=1                       /* found a match                */ 
  916.          if EncTypes.k.1~=missing then do
  917.             encode=upper(EncTypes.k.1)    /* store encode type            */
  918.             partlin=linenum               /* good starting point in file  */
  919.             if partnum=missing & encode='64' then partnum=1
  920.             CCdata=YES
  921.          end
  922.          leave k
  923.       end
  924.    end  /* do k=1 to EncTypes.0 */
  925.  
  926.    if TrapNewEncs=YES & matchctr=0 then do   /* must be a new encode type */ 
  927.       if exists(TrapNewEncsFile) then mode='A'
  928.                                  else mode='W'
  929.       goodopen=open('TRAPENCS',TrapNewEncsFile,mode)
  930.       if ~goodopen then do
  931.          msg='(E) Unable to open TrapEncFile:'TrapNewEncsFile
  932.          interpret Saycmd
  933.          msg='    Setting TrapNewEncs=NO'
  934.          interpret Saycmd
  935.       end
  936.       result=writeln('TRAPENCS',text)
  937.       result=close('TRAPENCS')
  938.    end  /* matches if TrapNewEncs=YES */
  939.  
  940. Return
  941.  
  942. /**************************************************************************/
  943. /*                                                                        */
  944. /*                     Handle Content-Disposition lines                   */
  945. /*                                                                        */
  946. /**************************************************************************/
  947. CheckCDisp:
  948.  
  949.    if pos('filename',word(text,3))=1 then do
  950.       partname=subword(text,3)
  951.       squote=pos('"',partname)
  952.       if squote>0 then do 
  953.          equote=lastpos('"',partname)-(squote+1)
  954.          partname=substr(partname,squote+1,equote)
  955.       end
  956.       else do
  957.          partname=strip(substr(partname,10)) 
  958.       end
  959.       CCdata=YES
  960.    end
  961.  
  962. CheckCDispEnd:
  963.  
  964. Return
  965.  
  966. /**************************************************************************/
  967. /*                                                                        */
  968. /*                     Handle the Base64 - type lines                     */
  969. /*                                                                        */
  970. /**************************************************************************/
  971. CheckBase64:
  972.  
  973.    do k=1 to Base64Types.0                /* loop thru various forms      */
  974.       key1=Base64Types.k                  /* primary search key           */
  975.       key1loc=1                           /* location of primary key      */
  976.       if pos(key1,text)=key1loc then do   /* found a match for Base64     */
  977.          partlin=linenum
  978.          encode='64'                      /* Base64 encoding              */
  979.          leave k                          /* stop looking                 */
  980.       end
  981.    end  /* do k=1 to Base64Types.0 */
  982.  
  983. Return
  984.  
  985. /**************************************************************************/
  986. /*                                                                        */
  987. /*  Read all unidentified files looking for UU encoded lines. Only files  */
  988. /*  with encode=missing are read. Should be part x/y and should only have */
  989. /*  a few lines of header info. Not like part 1/y where leading text may  */
  990. /*  be hundreds of lines. Use MaxHeader=25 or less and should be quick.   */
  991. /*                                                                        */
  992. /**************************************************************************/
  993. /* !!! BinHexed files are showing up as Base64 - !!! Modified 1/7/97      */
  994. /**************************************************************************/
  995. ReadUnknowns:
  996.  
  997. if verbose then say time() 'Reading unidentified files for encoded lines ...'
  998.  
  999.    do i=1 to Files.0
  1000.       if Files.i.1=missing then do        /* check file for encoded lines */
  1001.          filein=DWassignIN||Files.i
  1002.  
  1003.          goodopen=open('IN',filein,'R')
  1004.          if ~goodopen then do
  1005.             msg='(E) Error in processing input file' filein
  1006.             interpret Saycmd
  1007.             msg='    Attempting to continuing with next file'
  1008.             interpret Saycmd
  1009.             iterate
  1010.          end
  1011.  
  1012.          j=1                                     /* loop control variable */
  1013.          mcount=0                                /* reset UU line counter */
  1014.          bcount=0                                /* reset 64 line counter */
  1015.          bhfile=NO                               /* not a BinHex file     */
  1016.  
  1017.          do until j>MaxHeader | mcount=MinEncoded | eof('IN')
  1018.             linein=readln('IN')
  1019.             linein=strip(linein,'T')             /* strip trailing blanks */
  1020.             Select
  1021.                when substr(linein,1,1)='M' & pos(' ',linein)=0 then do
  1022.                   mcount=mcount+1
  1023.                   bcount=0                       /* if an 'M' then not 64 */
  1024.                end 
  1025.                when length(linein)>40 & pos(' ',linein)=0 then do
  1026.                   bcount=bcount+1 
  1027.                   mcount=0
  1028.                   end
  1029.                when linein='(This file must be converted with BinHex 4.0)' then do
  1030.                   bhfile=YES
  1031.                   bcount=0              
  1032.                   mcount=0
  1033.                   j=MaxHeader                 /* force end of loop     */
  1034.                end 
  1035.                otherwise nop
  1036.             end
  1037.             j=j+1                                /* NEXT line number      */
  1038.          end
  1039.  
  1040.          Select
  1041.             when mcount>=MinEncoded then do
  1042.                Files.i.1='UU'                    /* a UU encoded file     */
  1043.                Files.i.1.0=1                     /* 1 entry in array      */
  1044.             end 
  1045.             when bcount>=MinEncoded then do
  1046.                Files.i.1='64'                    /* Base 64 file?)        */
  1047.                Files.i.1.0=1        
  1048.             end 
  1049.             when bhfile=YES then do         
  1050.                Files.i.1='BH'                    /* Binhex file           */
  1051.                Files.i.1.0=1                     /* assume single part    */
  1052.                Files.i.1.1.1=1                   /* mark as a 1/y file    */
  1053. /*
  1054.                Files.i.1.1.1.1=1                 /* assume a 1/1 file !!! */
  1055. */
  1056.             end 
  1057.             otherwise nop
  1058.          end
  1059.          result=close('IN')                      /* close the input file  */
  1060.       end
  1061.    end
  1062.  
  1063. Return
  1064.  
  1065. /**************************************************************************/
  1066. /* First loop thru files and any that have multiples within a single file */
  1067. /* are marked as part 1/1. This assumes we don't have multiple PARTS for  */
  1068. /* files that have multiple encodes within them.                          */
  1069. /*                                                                        */
  1070. /*  Next:                                                                 */
  1071. /*  locate all encoded files with a missing value for name, num, or total */
  1072. /*  To complete this information we need to trust the information in the  */
  1073. /*  subject line and make some 'reasonalbe' assumptions. We will also     */
  1074. /*  use comparing of subject lines to connect part x/y with the part 1/y  */
  1075. /**************************************************************************/
  1076. Phase2:         
  1077.  
  1078. if verbose then say time() 'Starting Phase2 part identification ...'
  1079.  
  1080.    part1cnt=0                               /* count of part 1/. pieces   */
  1081.    partXcnt=0                               /* count of part x/y pieces   */
  1082.  
  1083.    do i=1 to Files.0        
  1084.       Select
  1085.          when Files.i.1=missing then nop    /* not an encoded file - skip */
  1086.          when Files.i.1.0=1 then do         /* 1 and only 1 part          */
  1087.             partname=Files.i.1.1
  1088.             partnum=Files.i.1.1.1
  1089.             parttot=Files.i.1.1.1.1
  1090.             if partname=missing | partnum=missing | parttot=missing then do
  1091.                Call CheckSubject
  1092.             end
  1093.             else do
  1094.                if parttot > 1 then do
  1095.                   Call CheckSubject
  1096.                end
  1097.             end
  1098.          end
  1099.          when Files.i.1.0>1 then do j=1 to Files.i.1.0 /* multiple in file*/
  1100.             if Files.i.1.j.1=1 & Files.i.1.j.1.1=missing then do
  1101.                Files.i.1.j.1.1=1
  1102.             end 
  1103.             else do
  1104.                if Files.i.1.j.1~=1 & Files.i.1.j.1.1=missing then do
  1105.                   Say 'Found multi parts with first not = 1'
  1106.                   Say Files.i Files.i.1 Files.i.1.j Files.i.1.j.1 Files.i.1.j.1.1
  1107.                end
  1108.             end
  1109.          end
  1110.          otherwise do
  1111.             if DEBUG then do
  1112.                Say 'Found otherwise condition in Phase2'
  1113.                Say Files.i Files.i.1 Files.i.1.0 Files.i.1.1 Files.i.1.1.1 Files.i.1.1.1.1
  1114.             end
  1115.          end
  1116.       end
  1117.    end
  1118.  
  1119.    Call Phase2Files
  1120.  
  1121. Return
  1122.  
  1123. /**************************************************************************/
  1124. /* Scan subject line looking for the partname previously identified. If   */
  1125. /* found mark where it/they occur.                                        */
  1126. /*                                                                        */
  1127. /* If we don't have a partname, then use the bintypes array to locate all */
  1128. /* potential filenames and mark where they occur.                         */
  1129. /*                                                                        */
  1130. /**************************************************************************/
  1131. CheckSubject:
  1132.  
  1133.    subjline=Subjinfo.i.1.1                     /* current subject line    */
  1134.    testword=missing                            /* init to missing         */
  1135.    spctr=0                                     /* counter for spartnames  */
  1136.    spartname.=missing                          /* init to missing         */
  1137.    spartname.0=0                               /* no partnames in subject */
  1138.    subjpn=missing                              /* init to missing         */
  1139.    subjpt=missing                              /* init to missing         */
  1140.    pncnt=0                                     /* counter for subject pns */
  1141.    ptcnt=0                                     /* counter for subject pts */
  1142.  
  1143.           /*****************************************************/
  1144.           /*  Get rid of all the braces, brackets, & parens.   */
  1145.           /*  This should take care of problems where user     */
  1146.           /*  didn't leave a blank between filename and part   */
  1147.           /*  information.                                     */
  1148.           /*                                                   */
  1149.           /*  Locate all possible binary file names in the     */
  1150.           /*  subject line. May be different ones or multiple  */
  1151.           /*  ones of the same name.                           */
  1152.           /*                                                   */
  1153.           /*  If a part 1/x (known from "begin" line) locate   */
  1154.           /*  if and where the partname is in the subject.     */
  1155.           /*  This will be used as a match locator in phase2.  */
  1156.           /*  If we can't locate it we will try to use the     */
  1157.           /*  partname we do find in the subject. (Probably a  */
  1158.           /*  typo by the user). If there isn't any name in    */
  1159.           /*  the subject we will use the entire subject line  */
  1160.           /*  for matches.                                     */
  1161.           /*                                                   */
  1162.           /*  For non 1/x parts, we try to get a subject name  */
  1163.           /*  and part information. This will be for reporting */
  1164.           /*  purposes only if we don't have the part 1 for it.*/
  1165.           /*                                                   */
  1166.           /*****************************************************/
  1167.  
  1168.    subjline=translate(subjline,'      ','()[]{}') 
  1169.  
  1170.           /*****************************************************/
  1171.           /*  Count possible file names in the subject line    */
  1172.           /*****************************************************/
  1173.  
  1174.    do k=1 to words(subjline)                    /* loop thru subject line */
  1175.       sword=word(subjline,k)                    /* copy for ease          */
  1176.       if partname~=missing then do              /* already have a name    */
  1177.          if upper(partname)=upper(sword) then do /* handle as found       */
  1178.             spctr=spctr+1                       /* count another          */
  1179.             spartname.0=spctr                   /* increment .0 ctr       */
  1180.             spartname.spctr=word(subjline,k)    /* store it               */
  1181.             spartname.spctr.1=k                 /* which word it is       */  
  1182.             iterate k                           /* skip bin type search   */
  1183.          end
  1184.       end
  1185.       do l=1 to Bintypes.0                      /* loop thru binary types */
  1186.          if upper(substr(sword,1,7))='HTTP://' then iterate
  1187.          if upper(substr(sword,1,4))='WWW.' & upper(right(sword,4))='.COM' then iterate
  1188.          if upper(right(sword,length(bintypes.l)))=upper(bintypes.l) then do
  1189.             spctr=spctr+1                       /* count another          */
  1190.             spartname.0=spctr                   /* increment .0 ctr       */
  1191.             spartname.spctr=word(subjline,k)    /* store it               */
  1192.             spartname.spctr.1=k                 /* which word it is       */  
  1193.             leave l                             /* only count first match */
  1194.          end
  1195.       end 
  1196.    end
  1197.  
  1198.  
  1199.           /*****************************************************/
  1200.           /*  if a part 1 - see how many subject part names    */
  1201.           /*  match actual begin name and where in subject.    */
  1202.           /*****************************************************/
  1203.    spctr=0                                      /* reset to zero b4 using */
  1204.    if partnum=1 then do                /* found via SECTION or begin line */
  1205.       part1cnt=part1cnt+1                       /* another part one piece */
  1206.       Partone.0=part1cnt                        /* store it               */
  1207.       Partone.part1cnt=i                        /* pointer to file array  */     
  1208.       Partone.part1cnt.1=partname               /* name of binary file    */
  1209.       Partone.part1cnt.1.0=0                    /* no matches yet         */
  1210.       Partone.part1cnt.1.1.1.1.1.1.1=subjline   /* store a copy           */
  1211.       if partname~=missing then do k=1 to spartname.0
  1212.          if upper(partname)=upper(spartname.k) then do
  1213.             spctr=spctr+1                       /* increment match ctr    */
  1214.             Partone.part1cnt.1.0=spctr          /* count it               */
  1215.             Partone.part1cnt.1.spctr=spartname.k.1 /* where in subject    */
  1216.          end
  1217.       end
  1218.       else do /* a part one without a part name */
  1219.          Partone.part1cnt.1.0=spartname.0     /* how many in subject line */
  1220.          do k=1 to spartname.0
  1221.             Partone.part1cnt.1.k=spartname.k.1  /* where in subject line  */
  1222.          end
  1223.       end
  1224.    end
  1225.    else do               /* NOT a part 1 piece -- store info for matching */
  1226.       partXcnt=partXcnt+1                       /* another part xxx piece */
  1227.       Partxxx.0=partXcnt                        /* store it               */
  1228.       Partxxx.partXcnt=i                        /* pointer to file array  */     
  1229.       Partxxx.partXcnt.1.1.1.1.1.1.1=subjline   /* store a copy           */
  1230.       if partname~=missing then Partxxx.partXcnt.1=partname /* know name  */
  1231.       Partxxx.partXcnt.1.0=spartname.0        /* how many in subject line */
  1232.       do k=1 to spartname.0
  1233.          Partxxx.partXcnt.1.k=spartname.k.1     /* where in subject line  */
  1234.       end
  1235.    end    /* matches else do - NOT a part 1 piece */
  1236.  
  1237.  
  1238.           /*****************************************************/
  1239.           /*    Look for x/y, (x/y), [x/y], {x/y} formats      */
  1240.           /*    and count how many occurrences                 */
  1241.           /*****************************************************/
  1242.           /*    IF MORE THAN 1 '/' in word skip that word.     */
  1243.           /*   (it is probably a date in the mm/dd/yy form)    */
  1244.           /*****************************************************/
  1245.  
  1246.    if partnum=missing | parttot=missing | parttot>1 then do 
  1247.       do j=1 to words(subjline)
  1248.          testword=word(subjline,j)
  1249.          if pos('/',testword)>0 then do
  1250.             if pos('/',testword)~=lastpos('/',testword) then iterate j
  1251.             testword=translate(testword,' ','/') /* strip "/" character   */
  1252.             pn=strip(word(testword,1))       
  1253.             pt=strip(word(testword,2))
  1254.             if datatype(pn,'N') & datatype(pt,'N') then do
  1255.                subjpn=strip(pn,'L','0')
  1256.                subjpt=strip(pt,'L','0')
  1257.                pncnt=pncnt+1                     /* found a subj part num */
  1258.                ptcnt=ptcnt+1                     /* found a subj total    */
  1259.                if partnum=1 then do              /* from section or begin */
  1260.                   Partone.part1cnt.1.1.0=pncnt   /* store subj part numcnt*/
  1261.                   Partone.part1cnt.1.1.pncnt=subjpn  /* store  part num   */
  1262.                   Partone.part1cnt.1.1.pncnt.1=j     /* which word in sub */
  1263.                   Partone.part1cnt.1.1.1.1.0=ptcnt /* store subj total cnt*/
  1264.                   Partone.part1cnt.1.1.1.1.ptcnt=subjpt /* store part tot */
  1265.                   Partone.part1cnt.1.1.1.1.ptcnt.1=j      /* word in subj */
  1266.                end
  1267.                else do
  1268.                   Partxxx.partXcnt.1.1.0=pncnt   /* store subj part numcnt*/
  1269.                   Partxxx.partXcnt.1.1.pncnt=subjpn  /* store  part num   */
  1270.                   Partxxx.partXcnt.1.1.pncnt.1=j     /* which word in sub */
  1271.                   Partxxx.partXcnt.1.1.1.1.0=ptcnt /* store subj total cnt*/
  1272.                   Partxxx.partXcnt.1.1.1.1.ptcnt=subjpt /* store part tot */
  1273.                   Partxxx.partXcnt.1.1.1.1.ptcnt.1=j      /* word in subj */
  1274.                end
  1275.             end
  1276.          end
  1277.       end
  1278.    end
  1279.  
  1280.           /*****************************************************/
  1281.           /*                                                   */
  1282.           /*       Look for partnumbers in form (xx of yy)     */
  1283.           /*                                                   */
  1284.           /*****************************************************/
  1285.  
  1286.    if partnum=missing | parttot=missing | parttot>1 then do 
  1287.       do j=2 to words(subjline)-1 by 1          /* loop thru subject line */
  1288.          of=word(subjline,j)                      /* copy it for ease     */
  1289.          if upper(of)='OF' then do
  1290.             pn=word(subjline,j-1)
  1291.             pt=word(subjline,j+1)
  1292.             pn=translate(pn,'       ','()[]{}/') 
  1293.             pt=translate(pt,'       ','()[]{}/') 
  1294.             pn=strip(pn)
  1295.             pt=strip(pt)
  1296.             if datatype(pn,'N') & datatype(pt,'N') then do
  1297.                subjpn=strip(pn,'L','0')
  1298.                subjpt=strip(pt,'L','0')
  1299.                pncnt=pncnt+1                     /* found a subj part num */
  1300.                ptcnt=ptcnt+1                     /* found a subj total    */
  1301.                if partnum=1 then do              /* from section or begin */
  1302.                   Partone.part1cnt.1.1.0=pncnt   /* store subj part numcnt*/
  1303.                   Partone.part1cnt.1.1.pncnt=subjpn  /* store  part num   */
  1304.                   Partone.part1cnt.1.1.pncnt.1=j-1   /* which word in sub */
  1305.                   Partone.part1cnt.1.1.1.1.0=ptcnt /* store subj total cnt*/
  1306.                   Partone.part1cnt.1.1.1.1.ptcnt=subjpt /* store part tot */
  1307.                   Partone.part1cnt.1.1.1.1.ptcnt.1=j+1    /* word in subj */
  1308.                end
  1309.                else do
  1310.                   Partxxx.partXcnt.1.1.0=pncnt   /* store subj part numcnt*/
  1311.                   Partxxx.partXcnt.1.1.pncnt=subjpn  /* store  part num   */
  1312.                   Partxxx.partXcnt.1.1.pncnt.1=j-1   /* which word in sub */
  1313.                   Partxxx.partXcnt.1.1.1.1.0=ptcnt /* store subj total cnt*/
  1314.                   Partxxx.partXcnt.1.1.1.1.ptcnt=subjpt /* store part tot */
  1315.                   Partxxx.partXcnt.1.1.1.1.ptcnt.1=j+1    /* word in subj */
  1316.                end
  1317.             end
  1318.          end
  1319.       end
  1320.    end
  1321.  
  1322.           /*****************************************************/
  1323.           /*                                                   */
  1324.           /*       Look for partnumbers in form (xxofyy)       */
  1325.           /*                                                   */
  1326.           /*****************************************************/
  1327.  
  1328.    if partnum=missing | parttot=missing | parttot>1 then do 
  1329.       do j=1 to words(subjline)                 /* loop thru subject line */
  1330.          of=word(subjline,j)                      /* copy it for ease     */
  1331.          if pos('OF',upper(of))>0 then do
  1332.             pn=substr(of,1,pos('OF',upper(of)))
  1333.             pt=substr(of,pos('OF',upper(of))+2)
  1334.             pn=translate(pn,'       ','()[]{}/') 
  1335.             pt=translate(pt,'       ','()[]{}/') 
  1336.             pn=strip(pn)
  1337.             pt=strip(pt)
  1338.             if datatype(pn,'N') & datatype(pt,'N') then do
  1339.                subjpn=strip(pn,'L','0')
  1340.                subjpt=strip(pt,'L','0')
  1341.                pncnt=pncnt+1                     /* found a subj part num */
  1342.                ptcnt=ptcnt+1                     /* found a subj total    */
  1343.                if partnum=1 then do              /* from section or begin */
  1344.                   Partone.part1cnt.1.1.0=pncnt   /* store subj part numcnt*/
  1345.                   Partone.part1cnt.1.1.pncnt=subjpn  /* store  part num   */
  1346.                   Partone.part1cnt.1.1.pncnt.1=j     /* which word in sub */
  1347.                   Partone.part1cnt.1.1.1.1.0=ptcnt /* store subj total cnt*/
  1348.                   Partone.part1cnt.1.1.1.1.ptcnt=subjpt /* store part tot */
  1349.                   Partone.part1cnt.1.1.1.1.ptcnt.1=j      /* word in subj */
  1350.                end
  1351.                else do
  1352.                   Partxxx.partXcnt.1.1.0=pncnt   /* store subj part numcnt*/
  1353.                   Partxxx.partXcnt.1.1.pncnt=subjpn  /* store  part num   */
  1354.                   Partxxx.partXcnt.1.1.pncnt.1=j     /* which word in sub */
  1355.                   Partxxx.partXcnt.1.1.1.1.0=ptcnt /* store subj total cnt*/
  1356.                   Partxxx.partXcnt.1.1.1.1.ptcnt=subjpt /* store part tot */
  1357.                   Partxxx.partXcnt.1.1.1.1.ptcnt.1=j      /* word in subj */
  1358.                end
  1359.             end
  1360.          end
  1361.       end
  1362.    end
  1363.   
  1364. Return
  1365.  
  1366. /**************************************************************************/
  1367. /*                                                                        */
  1368. /*   Attempt to fill out part 1/y information. The assumption is that if  */
  1369. /*   the partname is in the subject and the next word is a valid xx/yy    */
  1370. /*   or 'xx of yy' form, and 'xx'=1 THEN the yy portion is probably       */
  1371. /*   correct. A person could enter an invalid /yy portion, but unlikely.  */
  1372. /*                                                                        */
  1373. /*   If we find a word that fits these conditions, store where the part   */
  1374. /*   number and total are to be found for the final subject line match    */
  1375. /*   logic.                                                               */
  1376. /*                                                                        */
  1377. /**************************************************************************/
  1378. /*     need to handle name in subject but partnums aren't after the pn    */
  1379. /*     assume if we have one and only one 1/y then it is correct.         */
  1380. /*     with or without a partname in the subject. Done -                  */
  1381. /**************************************************************************/
  1382. Phase2Files:
  1383.  
  1384. If Debug then Say time() 'Starting 1/y condition ...'
  1385.  
  1386. /*                   Files                  spart      spart              */
  1387. /* Partone.  format: Pointer.partname.sword.number.loc.total.loc.subjline */
  1388.  
  1389.    do j=1 to Partone.0
  1390.       if Partone.j.1=missing then iterate        /* no partname anywhere  */
  1391.       if Partone.j.1.0>0 & Partone.j.1.1.1.1.0>0 then do  
  1392.          do k=1 to Partone.j.1.0                 /* check name matches    */   
  1393.             do l=1 to Partone.j.1.1.1.1.0        /* against total matches */
  1394.                nword=Partone.j.1.k               /* word with name        */
  1395.                pword=Partone.j.1.1.l.1           /* word with part number */
  1396.                tword=Partone.j.1.1.1.1.l.1       /* word with total value */
  1397.                if pword=tword then nword=nword+1 /* an xx/yy or xxofyy    */
  1398.                               else nword=nword+3 /* an xx of yy form      */
  1399.                testpn=Partone.j.1.1.l            /* xx portion of xx/yy   */
  1400.                if nword=tword & testpn=1 then do
  1401.                   fptr=Partone.j                 /* pointer to files array*/
  1402.                   Files.fptr.1.1.1.1=Partone.j.1.1.1.1.l /* assume correct*/
  1403.                   Partone.j.1.1.1.0=l            /* entry of partnumber   */
  1404.                   Partone.j.1.1.1.1.1.0=l        /* entry of total number */
  1405.                   iterate j                      /* go on to next partone.*/ 
  1406.                end               
  1407.             end
  1408.          end             /* next see if xx/yy is separated from part name */ 
  1409.          if Partone.j.1.1.0=1  & Partone.j.1.1.1.1.0=1 then do   
  1410.             testpn=Partone.j.1.1.1               /* xx portion of xx/yy   */
  1411.             if testpn=1 then do                  /* only one and it is 1/y*/
  1412.                fptr=Partone.j                    /* pointer to files array*/
  1413.                Files.fptr.1.1.1.1=Partone.j.1.1.1.1.1    /* assume correct*/
  1414.                Partone.j.1.1.1.0=1               /* entry of partnumber   */
  1415.                Partone.j.1.1.1.1.1.0=1           /* entry of total number */
  1416.                iterate j                         /* go on to next partone.*/ 
  1417.             end 
  1418.          end
  1419.       end   /* matches with partname and parttotal in subject             */
  1420.       else do   /* probably no partname in subject use xx/yy if single    */  
  1421.          if Partone.j.1.1.0=1  & Partone.j.1.1.1.1.0=1 then do   
  1422.             testpn=Partone.j.1.1.1               /* xx portion of xx/yy   */
  1423.             if testpn=1 then do                  /* only one and it is 1/y*/
  1424.                fptr=Partone.j                    /* pointer to files array*/
  1425.                Files.fptr.1.1.1.1=Partone.j.1.1.1.1.1    /* assume correct*/
  1426.                Partone.j.1.1.1.0=1               /* entry of partnumber   */
  1427.                Partone.j.1.1.1.1.1.0=1           /* entry of total number */
  1428.                iterate j                         /* go on to next partone.*/ 
  1429.             end 
  1430.          end
  1431.       end
  1432.    end
  1433.  
  1434. /**************************************************************************/
  1435. /*                                                                        */
  1436. /*   Big Assumption Time: If NO total has been found anywhere (section,   */
  1437. /*   mime, or subject) then ASSUME that it is a (1/1). This happens for   */
  1438. /*   a lot of files. The subject just says 'xxxx.jpg' and some text.      */
  1439. /*   The other form is a subject with 1/1 but without the part name.      */
  1440. /*   Consider these valid 1/1 parts also.                                 */
  1441. /*                                                                        */
  1442. /**************************************************************************/
  1443. Phase2Scan:
  1444.  
  1445. If Debug then Say time() 'Starting 1/1 Scanning  ...'
  1446.  
  1447.    do j=1 to Partone.0                           /* loop thru part names  */
  1448.       if Partone.j.1.1.1.1.0=missing then do     /* check all w/o a total */  
  1449.          Partone.j.1.1.1.1.0=1                   /* set as if in sub      */
  1450.          Partone.j.1.1.1.1.1=1                   /* set to value 1        */
  1451.          fptr=Partone.j                          /* pointer to files array*/
  1452.          Files.fptr.1.1.1.1=1                    /* fix in files.         */
  1453.       end
  1454.       else do                                    /* total not missing     */
  1455.          /**********************************************************/
  1456.          /* only one [1/1] in the subject, but partname is not in  */
  1457.          /* a begin line/section/etc. OR not in the subject.       */
  1458.          /*   Consider these valid 1/1 parts also.                 */
  1459.          /**********************************************************/
  1460.          if Partone.j.1.1=missing | Partone.j.1=missing then do
  1461.             if Partone.j.1.1.1.1.0=1 & Partone.j.1.1.1.1.1=1 then do
  1462.                fptr=Partone.j                    /* pointer to files array*/
  1463.                Files.fptr.1.1.1.1=1              /* fix in files.         */
  1464.             end
  1465.          end
  1466.       end
  1467.    end
  1468.  
  1469. Phase2ScanEnd:
  1470.  
  1471. /**************************************************************************/
  1472. /*                                                                        */
  1473. /*   The last group to process in Partone. are the 1/y with information   */
  1474. /*   in the subjects. We will do some comparing against the Partxxx array */
  1475. /*   to try to FIRMLY connect the xx/yy parts to the part 1/yy.           */
  1476. /*                                                                        */
  1477. /**************************************************************************/
  1478. Phase2Match:
  1479.  
  1480. If Debug then Say time() 'Starting 1/yy to xx/yy matching ...'
  1481. /*
  1482. say 'j fptr p1match p1tots pval offset p1word'
  1483. */
  1484.    do j=1 to Partone.0                           /* last time thru loop   */
  1485.       if Partone.j.1=missing then iterate        /* missing partname      */
  1486.       if Partone.j.1.1.1.1.0>0 then do           /* check all with totals */  
  1487.          fptr=Partone.j                          /* pointer to files      */
  1488.          if Files.fptr.1.1.1.1>1 then do         /* yep, a 1/y, not a 1/1 */
  1489.             p1match=Partone.j.1.1.1.1.1.1.1      /* subject line          */
  1490.             p1tots=Partone.j.1.1.1.1.0           /* number of tots in sub */
  1491.             pval=Partone.j.1.1.1.0  /* identified in Phase2Files as valid */
  1492.             if pval=missing then pval=Partone.j.1.1.0 /* use LAST PN      */
  1493.             offset=-1                            /* needed for shrinking  */ 
  1494.             do k=1 to Partone.j.1.1.0            /* remove xx word subj   */
  1495.                offset=offset+1                   /* for next time         */
  1496.                p1word=Partone.j.1.1.k.1          /* word to remove        */ 
  1497. /*
  1498. say 'Partone.j.1.1.0='Partone.j.1.1.0
  1499. say j fptr p1match p1tots pval offset p1word
  1500. */
  1501.                p1word=p1word-offset              /* correction factor     */ 
  1502.                p1match=delword(p1match,p1word,1) 
  1503.             end
  1504.             do m=1 to Partxxx.0                  /* now loop thru xx/yy   */
  1505.                p2match=Partxxx.m.1.1.1.1.1.1.1   /* subject line          */
  1506.                p2tots=Partxxx.m.1.1.1.1.0        /* number of tots in sub */
  1507.                if p2tots~=p1tots then iterate m  /* must be different     */
  1508.                do n=1 to p1tots                  /* compare totals        */
  1509.                  if Partone.j.1.1.1.1.n ~= Partxxx.m.1.1.1.1.n then iterate m
  1510.                end
  1511.                Xptr=Partxxx.m                    /* pointer to files array*/
  1512.                offset=-1                         /* needed for shrinking  */ 
  1513.                do k=1 to Partxxx.m.1.1.0         /* remove xx word subj   */
  1514.                   offset=offset+1                /* for next time         */
  1515.                   p1word=Partone.j.1.1.k.1       /* word to remove        */ 
  1516. /*
  1517. say j fptr p1match p1tots pval offset p1word
  1518. */
  1519.                   p1word=p1word-offset           /* correction factor     */ 
  1520.                   p2match=delword(p2match,p1word,1) /* remove same here   */
  1521.                end
  1522.                if p1match=p2match then do            /* should be a match */
  1523.                   Files.Xptr.1.1=Partone.j.1         /* name from part1   */
  1524.                   Files.Xptr.1.1.1=Partxxx.m.1.1.pval
  1525.                   Files.Xptr.1.1.1.1=Partxxx.m.1.1.1.1.pval 
  1526.                   Partxxx.m.1=Partone.j.1             /* name from part1  */
  1527.                end
  1528.             end   /* matches do m=1 to Partxxx.0 */
  1529.          end   /* matches if Files.fptr.1.1>1    */
  1530.       end   /* matches if Partone.j.1.1.1.1.0>0  */
  1531.    end   /* matches do j=1 to Partone.0          */
  1532.  
  1533. Phase2MatchEnd:
  1534.  
  1535. /**************************************************************************/
  1536. /*                                                                        */
  1537. /*   The final group of files are part x/y that failed matching with a    */
  1538. /*   part 1/y. They also had no MIME or Section information available.    */
  1539. /*   Let's TRUST the subject for information IFF there is ONLY 1 partname */
  1540. /*   possible we will use it. Similarly for x/y information. IFF there is */
  1541. /*   only 1 potential partnum/parttot we will use it. If missing or mult- */
  1542. /*   iple, we give it up.                                                 */
  1543. /*   Do this for the Partones also but only if B64 or BinHex.             */
  1544. /**************************************************************************/
  1545. /* Need to allow for multiple names in subject that are ALL THE SAME      */
  1546. /* then treat them as correct. Done.                                      */
  1547. /**************************************************************************/
  1548. Phase2FinalTry:
  1549.  
  1550. If Debug then Say time() 'Starting use subject only ...'
  1551.  
  1552.    do j=1 to Partxxx.0                           /* last time thru loop   */
  1553.       Xptr=Partxxx.j                             /* pointer to files array*/
  1554.  
  1555.       /* if unknown partname AND only 1 potential name in subject - use it*/
  1556.       if Files.Xptr.1~=missing & Files.Xptr.1.1=missing then do
  1557.          AllSame=YES                             /* flag for testing      */
  1558.          pXnams=Partxxx.j.1.0                    /* numb of names in sub  */
  1559.          if pXnams>0 then do                     /* see if all the same   */
  1560.             sword=Partxxx.j.1.1                  /* which word in subject */
  1561.             subject=Partxxx.j.1.1.1.1.1.1.1      /* subject line          */
  1562.             savename=word(subject,sword)         /* save the first one    */
  1563.             do k=1 to Partxxx.j.1.0              /* loop thru them        */
  1564.                sword=Partxxx.j.1.k               /* which word in subject */
  1565.                partname=word(subject,sword)      /* nth name in subject   */
  1566.                if partname ~= savename then do   /* different name found  */
  1567.                   AllSame=NO                     /* set flag              */
  1568.                   leave k                        /* quit looking          */
  1569.                end 
  1570.             end
  1571.             if AllSame then Files.Xptr.1.1=partname  /* ALL were the same */
  1572.          end
  1573.       end
  1574.  
  1575.       /* if unknown partnum AND only 1 potential name in subject - use it*/
  1576.       if Files.Xptr.1~=missing & Files.Xptr.1.1.1=missing then do
  1577.          pXnums=Partxxx.j.1.1.0                  /* number of nums in sub */
  1578.          if pXnums=1 then Files.Xptr.1.1.1=Partxxx.j.1.1.1
  1579.       end
  1580.  
  1581.       /* if unknown parttot AND only 1 potential name in subject - use it*/
  1582.       if Files.Xptr.1~=missing & Files.Xptr.1.1.1.1=missing then do
  1583.          pXtots=Partxxx.j.1.1.1.1.0              /* number of tots in sub */
  1584.          if pXtots=1 then Files.Xptr.1.1.1.1=Partxxx.j.1.1.1.1.1
  1585.       end
  1586.    end
  1587.  
  1588.    do j=1 to Partone.0                           /* last time thru loop   */
  1589.       ptr=Partone.j                              /* pointer to files array*/
  1590.  
  1591.       /* if Partname missing AND B64 and only 1 potential name - use it   */
  1592.       if (Files.ptr.1='64' | Files.ptr.1='BH') & Files.ptr.1.1=missing then do
  1593.          pnams=Partone.j.1.0                     /* numb of names in sub  */
  1594.          if pnams=1 then do
  1595.             sword=Partone.j.1.1
  1596.             subject=Partone.j.1.1.1.1.1.1.1
  1597.             partname=word(subject,sword)
  1598.             Files.ptr.1.1=partname
  1599.          end
  1600.       end
  1601.    end
  1602.  
  1603. Return
  1604.  
  1605. /**************************************************************************/
  1606. /*                                                                        */
  1607. /*               Report File information in this Phase                    */
  1608. /*                                                                        */
  1609. /* Generate report of all input files for this directory at this point in */
  1610. /* the processing.                                                        */
  1611. /*                                                                        */
  1612. /* Logic: Loop thru Files array picking up the information from the other */
  1613. /* arrays as necessary.                                                   */
  1614. /*                                                                        */
  1615. /**************************************************************************/
  1616. ReportFiles:
  1617.  
  1618.    if ~ShowFiles then signal ReportFilesEnd
  1619.    msg=' '
  1620.    interpret Saycmd
  1621.    msg=dirlist.dirptr ' Processing: ' Files.0 'File(s)'
  1622.    interpret Saycmd   
  1623.    msg=left(dashes,length(msg))   
  1624.    interpret Saycmd   
  1625.  
  1626.    do rptptr=1 to files.0                     /* loop thru files array    */
  1627.       msg='Filename:' Files.rptptr               /* report name of file   */
  1628.       interpret Saycmd
  1629.       msg='Subject: ' Subjinfo.rptptr.1.1        /* report subject line   */
  1630.       interpret Saycmd
  1631.  
  1632.       select
  1633.          when Files.rptptr.1=missing then do 
  1634.             msg='Encoding: Not an encoded file'
  1635.             interpret Saycmd
  1636.             msg=' '
  1637.             interpret Saycmd
  1638.          end
  1639.          when Files.rptptr.1='UU' then do 
  1640.             msg='Encoding: UUencode'
  1641.             interpret Saycmd
  1642.             do pptr=1 to Files.rptptr.1.0
  1643.                msg='Name:    ' Files.rptptr.1.pptr
  1644.                interpret Saycmd
  1645.                msg='Part:    ' Files.rptptr.1.pptr.1 'of' Files.rptptr.1.pptr.1.1
  1646.                interpret Saycmd
  1647.             end
  1648.             msg=' '
  1649.             interpret Saycmd
  1650.          end
  1651.          when Files.rptptr.1='64' then do 
  1652.             msg='Encoding: Base64'
  1653.             interpret Saycmd
  1654.             do pptr=1 to Files.rptptr.1.0
  1655.                msg='Name:    ' Files.rptptr.1.pptr
  1656.                interpret Saycmd
  1657.                msg='Part:    ' Files.rptptr.1.pptr.1 'of' Files.rptptr.1.pptr.1.1
  1658.                interpret Saycmd
  1659.             end
  1660.             msg=' '
  1661.             interpret Saycmd
  1662.          end
  1663.          when Files.rptptr.1='BH' then do 
  1664.             msg='Encoding: BinHex'
  1665.             interpret Saycmd
  1666.             do pptr=1 to Files.rptptr.1.0
  1667.                msg='Name:    ' Files.rptptr.1.pptr
  1668.                interpret Saycmd
  1669.                msg='Part:    ' Files.rptptr.1.pptr.1 'of' Files.rptptr.1.pptr.1.1
  1670.                interpret Saycmd
  1671.             end
  1672.             msg=' '
  1673.             interpret Saycmd
  1674.          end
  1675.          otherwise encoding=Files.rptptr.1       /* should never happen   */
  1676.       end
  1677.    end
  1678.  
  1679. ReportFilesEnd:
  1680.  
  1681. Return
  1682.  
  1683. /**************************************************************************/
  1684. /*                                                                        */
  1685. /*               Create arrays as needed for processing.                  */
  1686. /*                                                                        */
  1687. /**************************************************************************/
  1688. BuildLists:
  1689.    
  1690.    Temppart.0=0
  1691.    if Files.0>0 then do
  1692.       msg=' '
  1693.       interpret Saycmd 
  1694.    end
  1695.  
  1696.    errorcnt=0
  1697.    pnlen=0                                      /* length of partname     */
  1698.    fnlen=0                                      /* length of filename     */
  1699.   
  1700.    Do fptr=1 to Files.0
  1701.       filename=Files.fptr
  1702.       encode=Files.fptr.1                       /* encoding method        */
  1703.       if encode=missing then iterate            /* not encoded            */
  1704.       Do pptr=1 to Files.fptr.1.0               /* loop thru partnames    */
  1705.          partname=Files.fptr.1.pptr
  1706.          partname=translate(partname,tab,' ')   /* for names with blanks  */
  1707.          partnum =Files.fptr.1.pptr.1
  1708.          parttot =Files.fptr.1.pptr.1.1
  1709.          pnlen=max(pnlen,length(partname))      /* longest length for rpt */
  1710.          fnlen=max(fnlen,length(filename))      /* longest length for rpt */
  1711.  
  1712.          if partnum~=missing & parttot~=missing & partname~=missing & ,
  1713.             filename~=missing then do
  1714.                Temppart.0=1+Temppart.0
  1715.                ptr=Temppart.0
  1716.                Temppart.ptr=partname encode parttot partnum filename fptr pptr
  1717.          end
  1718.          else do
  1719.            if errorcnt=0 then do
  1720.               msg='Errors: Filename Encode Partname Partnum Parttot Pptr ("."=missing)'
  1721.               interpret saycmd
  1722.               msg=left(dashes,length(msg))
  1723.               interpret Saycmd
  1724.               errorcnt=1
  1725.            end
  1726.            msg='(E) Missing information for file:' filename encode partname partnum parttot pptr
  1727.            interpret saycmd
  1728.          end
  1729.       end
  1730.    end
  1731.  
  1732.    pnlen=min(pnlen,30)                          /* maximum Amiga name len */
  1733.  
  1734.    if show('L','rexxtricks.library') then do    /* use tricks library     */
  1735.       call QSORT(Temppart)                      /* put into order         */
  1736.    end
  1737.    else do                                      /* use QuickSort          */
  1738.       call QSORT(1, Temppart.0, Temppart)       /* put into order         */
  1739.    end
  1740.  
  1741.  
  1742.  
  1743.    if DEBUG=YES then do
  1744.       msg=' '
  1745.       interpret Saycmd
  1746.        msg='Dumping Temppart array:'
  1747.        interpret saycmd
  1748.        msg=left(dashes,length(msg))
  1749.        interpret Saycmd
  1750.        do j=1 to Temppart.0
  1751.           msg=Temppart.j
  1752.           interpret Saycmd
  1753.        end
  1754.        msg=' '
  1755.        interpret Saycmd
  1756.    end
  1757.  
  1758.    oldname=missing
  1759.    oldtotal=missing
  1760.    oldencode=missing
  1761.    Parts.=missing
  1762.    Parts.0=0
  1763.  
  1764.    do j=1 to Temppart.0
  1765.       if word(Temppart.j,1)~=oldname | word(Temppart.j,2)~=oldencode |,
  1766.          word(Temppart.j,3)~=oldtotal then do
  1767.          oldname=word(Temppart.j,1)              /* Save to old name      */         
  1768.          oldencode=word(Temppart.j,2)            /* Save to old encode    */
  1769.          oldtotal=word(Temppart.j,3)             /* Save to old total     */
  1770.          Parts.0=1+Parts.0                       /* a new partname        */
  1771.          ptr=Parts.0                             /* count it              */
  1772.          partname=word(Temppart.j,1)             /* get partname          */
  1773.          partname=translate(partname,' ',tab)    /* return blanks to name */
  1774.          Parts.ptr=partname                      /* store partname        */     
  1775.          Parts.ptr.1=word(Temppart.j,3)          /* Total Parts Expected  */
  1776.          partnum=word(Temppart.j,4)              /* part number sets slot */   
  1777.          filename=word(Temppart.j,5)             /* filename              */   
  1778.          fptr=word(Temppart.j,6)                 /* pointer into Files.   */
  1779.          pptr=word(Temppart.j,7)                 /* pointer for partname  */
  1780.          Parts.ptr.1.partnum=filename            /* store it in pn slot   */
  1781.          Parts.ptr.1.partnum.1=fptr              /* pointer into Files.   */
  1782.          Parts.ptr.1.partnum.1.1=pptr            /* pointer to part info  */
  1783.          Parts.ptr.1.0=1                         /* indicate 1 part found */
  1784.       end
  1785.       else do
  1786.          partnum=word(Temppart.j,4)              /* part number sets slot */   
  1787.          filename=word(Temppart.j,5)             /* filename              */   
  1788.          fptr=word(Temppart.j,6)                 /* pointer into Files.   */
  1789.          pptr=word(Temppart.j,7)                 /* pointer for partname  */
  1790.          if Parts.ptr.1.partnum=missing then do  /* slot not already used */
  1791.             Parts.ptr.1.0=1+Parts.ptr.1.0        /* 1 more part found     */
  1792.          end  /* don't count mult. but use nth version - fixes Apple/DBL  */
  1793.          else do
  1794.             oldfptr=Parts.ptr.1.partnum.1
  1795.             oldpptr=Parts.ptr.1.partnum.1.1
  1796.             miscinfo.oldfptr.oldpptr.1.1.1.1=YES /* mark as duplicate     */
  1797.          end
  1798.          Parts.ptr.1.partnum=filename            /* put filename in it    */
  1799.          Parts.ptr.1.partnum.1=fptr              /* pointer into Files.   */
  1800.          Parts.ptr.1.partnum.1.1=pptr            /* pointer to part info  */
  1801.       end
  1802.    end
  1803.  
  1804.    if ~ShowParts then signal BuildListsEnd
  1805.    if  parts.0=0 then signal BuildListsEnd
  1806.  
  1807.    msg=' '
  1808.    interpret Saycmd
  1809.    msg='Encoded parts:'
  1810.    interpret saycmd
  1811.    msg='Output name'
  1812.    msg=overlay('xxx of yyy',msg,pnlen+5)
  1813.    msg=overlay('Input Name',msg,length(msg)+5)
  1814.    interpret saycmd
  1815.    msg=left(dashes,length(msg))
  1816.    interpret Saycmd
  1817.  
  1818.  
  1819.    do j=1 to Parts.0 
  1820.       msg=' ' 
  1821.       interpret saycmd
  1822.       do k=1 to Parts.j.1
  1823.          msg=substr(Parts.j,1,pnlen)
  1824.          msg=overlay(k,msg,pnlen+8-length(k))
  1825.          msg=overlay('of',msg,length(msg)+2)
  1826.          msg=overlay(Parts.j.1,msg,length(msg)+2)
  1827.          tfile=right(parts.j.1.k,fnlen)
  1828.          msg=overlay(tfile,msg,length(msg)+8-length(Parts.j.1))
  1829.          interpret Saycmd
  1830.       end
  1831.    end
  1832.    msg=' '
  1833.    interpret Saycmd
  1834.  
  1835. BuildListsEnd:
  1836.  
  1837. Return
  1838.  
  1839. /**************************************************************************/
  1840. /*                                                                        */
  1841. /*                       Finally do the Decoding.                         */
  1842. /*             Strip ALL PATH information prior to decoding.              */
  1843. /**************************************************************************/
  1844. DecodeFiles:
  1845.  
  1846.    if verbose then say time() 'Starting Decoding ...' 
  1847.  
  1848.    pragma('D',dest)                    /* change directory to destination */
  1849.    curdir=pragma('D')                  /* check to make sure changed      */
  1850.  
  1851.  
  1852.    if ShowDecode & parts.0 > 0 then do
  1853.       msg=' '
  1854.       interpret Saycmd
  1855.       msg='Decoding to Directory ... 'curdir
  1856.       interpret Saycmd
  1857.       msg=left(dashes,length(msg))
  1858.       interpret Saycmd
  1859.       msg=' '
  1860.       interpret Saycmd
  1861.    end
  1862.  
  1863.    do i=1 to parts.0                       /* loop thru all output files  */
  1864.       if parts.i.1=parts.i.1.0 then do     /* we have all necessary parts */
  1865.          Filesptr=parts.i.1.1.1            /* pointer into Files array    */
  1866.          Pptr=parts.i.1.1.1.1              /* pointer to part within file */
  1867.          encode=Files.filesptr.1           /* type of encoding            */
  1868.          partname=parts.i                  /* get partname for decoding   */
  1869.          if pos('/',partname)>0 then do    /* strip path information      */
  1870.             partname=substr(partname,lastpos('/',partname)+1)
  1871.          end
  1872.          else do
  1873.             if pos(':',partname)>0 then do 
  1874.                partname=substr(partname,lastpos(':',partname)+1)
  1875.             end
  1876.          end         
  1877.          msg=substr(partname,1,pnlen)      /* name of output file         */
  1878.          filestr=''                        /* init to null on new partname*/  
  1879.          if encode='UU' then msgenc='UU  decoding from -'
  1880.                         else msgenc='B64 decoding from -' 
  1881.          msg=overlay(msgenc,msg,pnlen+3)
  1882.  
  1883.          if replace=NO then do             /* check replace output file   */
  1884.             if exists(partname) then do     /* already exists              */
  1885.                if Miscinfo.Filesptr.pptr.1=missing then do /* decode~=YES */
  1886.                   filestr=''               /* init to null for file list  */
  1887.                   do k=1 to parts.i.1      /* build list of files skipped */  
  1888.                      tfile=right(parts.i.1.k,fnlen)
  1889.                      tfptr=parts.i.1.k.1   /* file pointer for this part  */
  1890.                      tpptr=parts.i.1.k.1.1
  1891.                      Miscinfo.tfptr.tpptr.1.1.1.1=YES /* duplicate output */ 
  1892.                      if filestr='' then filestr=tfile
  1893.                                    else filestr=filestr||' '||tfile
  1894.                   end  
  1895.                   msg=substr(partname,1,pnlen) /* reset to just partname  */
  1896.                   msg=overlay('exists; skipping  -',msg,pnlen+3)
  1897.                   msg=overlay(Filestr,msg,length(msg)+3)
  1898.                   if ShowDecode then interpret SayCmd
  1899.                   iterate i
  1900.                end
  1901.                else do  /* we decoded it as part of another partname      */
  1902.                   filestr=parts.i.1.1      /* should be 1/1 of another    */
  1903. say 'Hit else do in REPLACE=NO of decodefiles: for ' filestr files.filesptr
  1904.                   Call IssueDecodeMsg
  1905.                   Call FileNoteOut
  1906.                   iterate i
  1907.                end
  1908.             end
  1909.          end
  1910.  
  1911.          Call BldDecodeStr
  1912.  
  1913.          Select /* !!! added */
  1914.             When encode='UU' then Call DecodeUUFiles
  1915.             When encode='64' then Call Decode64Files
  1916.             When encode='BH' then Call DecodeBHFiles
  1917.             otherwise do
  1918.                if DEBUG then do
  1919.                   say 'Found otherwise line 1945 for i='i 'encode='encode 'filesptr='filesptr
  1920.                end
  1921.             end
  1922.          end
  1923.  
  1924.       end   /* matches parts.i.1=parts.i.1.0 */
  1925.    end   /* matches do i=1 to parts.0 */
  1926.  
  1927. /**************************************************************************/
  1928. /*                                                                        */
  1929. /*   Handle DELETEAFTER and DELETEDUPS options.                           */
  1930. /*                                                                        */
  1931. /*   Delete any decoded files and any duplicates, but only IF  no errors  */
  1932. /*   The CHOPPED files may have duplicate names and decoded in a single   */
  1933. /*   file and the possibility there was an error for only 1 of the pieces.*/
  1934. /*                                                                        */
  1935. /*   The files that weren't chopped only need to be checked if delete     */
  1936. /*   duplicates was specified. If so then the dup flag is set in Miscinfo.*/
  1937. /*                                                                        */
  1938. /**************************************************************************/
  1939.  
  1940.    do i=1 to Files.0
  1941.       deccnt=0
  1942.       dupcnt=0
  1943.       delflag=NO
  1944.       partcnt=Files.i.1.0
  1945.       if partcnt=0 then iterate i
  1946.       do j=1 to partcnt
  1947.          if Miscinfo.i.j.1=YES then deccnt=deccnt+1
  1948.          if Miscinfo.i.j.1.1.1.1=YES then dupcnt=dupcnt+1
  1949.       end
  1950.       if DeleteAfter & deccnt>0 & deccnt+dupcnt=partcnt then delflag=YES
  1951.       if DeleteDups & dupcnt=partcnt then delflag=YES
  1952.       if delflag & ~scanonly then do
  1953.          Address Command 'Delete ' DWassignIn||Files.i 'QUIET'
  1954.       end
  1955.    end
  1956.  
  1957.    pragma('D',progdir)                     /* change dir back to progdir  */
  1958.    curdir=pragma('D')                      /* check to make sure changed  */
  1959.  
  1960.    if debug then do
  1961.       msg=' '
  1962.       interpret Saycmd
  1963.       msg='Changing Directory to ... 'curdir
  1964.       interpret Saycmd
  1965.       msg=' '
  1966.       interpret Saycmd
  1967.    end
  1968.  
  1969. DecodeFilesEnd:
  1970.  
  1971.    if verbose then say time() 'Done Decoding ...' 
  1972.    
  1973. Return
  1974.    
  1975. /**************************************************************************/
  1976. /*                                                                        */
  1977. /*                Handle chopping, joining, ect. for decoding             */
  1978. /*                                                                        */
  1979. /**************************************************************************/
  1980. BldDecodeStr:
  1981.  
  1982.    joinstr=''                                       /* init to null       */
  1983.    chopflag=NO                                      /* no chopping done   */
  1984.  
  1985.    Select
  1986.       when parts.i.1=1 & Files.filesptr.1.0=1 then do /* a single 1/1 file*/
  1987.          filestr=right(parts.i.1.1,fnlen)           /* name of file       */
  1988.          filein=DWassignIN||parts.i.1.1             /* with assign path   */
  1989.          Miscinfo.Filesptr.pptr.1=YES               /* mark as decoded    */
  1990.          Call IssueDecodeMsg
  1991.       end         
  1992.       when parts.i.1=1 & Files.filesptr.1.0>1 then do
  1993.          filein=DWassignIN||parts.i.1.1             /* with assign path   */
  1994.          if Miscinfo.Filesptr.pptr.1.1.1=missing then Call ChopFile
  1995.          filestr=right(parts.i.1.1,fnlen)
  1996.          filein=DWtemp||Files.filesptr||'.'||pptr   /* build chopped name */
  1997.          Miscinfo.Filesptr.pptr.1=YES               /* mark as decoded    */
  1998.          Call IssueDecodeMsg
  1999.          chopflag=YES                            /* filein is a T:CHOPPED */
  2000.       end
  2001.       when parts.i.1>1 then do
  2002.          filestr=''
  2003.          do k=1 to parts.i.1          /* loop thru list of files required */              
  2004.             Filesptr=parts.i.1.k.1         /* pointer into Files array    */
  2005.             do j=1 to Files.Filesptr.1.0   /* mark all multi's as decoded */
  2006.                Miscinfo.Filesptr.j.1=YES   /* mark as decoded             */
  2007.             end
  2008.             tfile=right(parts.i.1.k,fnlen)
  2009.             if filestr='' then filestr=tfile
  2010.                           else filestr=filestr||' '||tfile
  2011.             joinstr=joinstr||' '||DWassignIN||parts.i.1.k
  2012.          end  /* matches do k=1 to parts.i.1 */              
  2013.          Call IssueDecodeMsg
  2014.          filein=DWtemp'DWdecode.temp' 
  2015.          Address Command 'Join ' joinstr 'AS' filein
  2016.          joinrc=rc
  2017.          if joinrc>0 then do
  2018.             say '   JOIN returned rc='joinrc 'for 'partname
  2019.             say joinstr 'AS' filein
  2020.          end
  2021.       end
  2022.       otherwise do
  2023.         if DEBUG then do
  2024.            say 'Found otherwise in BldDecodeStr for :'parts.i Files.filesptr
  2025.         end
  2026.         signal BldDecodeStrEnd
  2027.       end
  2028.    End
  2029.  
  2030. BldDecodeStrEnd:
  2031.  
  2032. Return
  2033.  
  2034. /**************************************************************************/
  2035. /*                                                                        */
  2036. /*                Handle the UU encoded decoding.                         */
  2037. /*                                                                        */
  2038. /**************************************************************************/
  2039. DecodeUUFiles:
  2040.  
  2041.    if scanonly=yes then signal DecodeUUFilesEnd
  2042.  
  2043.    UUcmdx=UUcmd                                  /* copy for replacement  */
  2044.  
  2045.    do j=1 to words(UUcmdx)
  2046.       select
  2047.         when upper(word(UUcmdx,j))='%SF' then do
  2048.            wptr=wordindex(UUcmdx,j)-1
  2049.            UUcmdx=delword(UUcmdx,j,1)
  2050.            UUcmdx=insert(filein,UUcmdx,wptr,length(filein)+1,' ')
  2051.         end
  2052.         when upper(word(UUcmdx,j))='%DF' then do
  2053.            wptr=wordindex(UUcmdx,j)-1
  2054.            UUcmdx=delword(UUcmdx,j,1)
  2055.            destfile=dest||partname
  2056.            UUcmdx=insert(destfile,UUcmdx,wptr,length(destfile)+1,' ')
  2057.         end
  2058.         when upper(word(UUcmdx,j))='%SD' then do
  2059.            wptr=wordindex(UUcmdx,j)-1
  2060.            UUcmdx=delword(UUcmdx,j,1)
  2061.            UUcmdx=insert(source,UUcmdx,wptr,length(source)+1,' ')
  2062.         end
  2063.         when upper(word(UUcmdx,j))='%DD' then do
  2064.            wptr=wordindex(UUcmdx,j)-1
  2065.            UUcmdx=delword(UUcmdx,j,1)
  2066.            UUcmdx=insert(dest,UUcmdx,wptr,length(dest)+1,' ')
  2067.         end
  2068.         otherwise nop
  2069.       end
  2070.    end   
  2071.  
  2072.    Address Command UUcmdx 
  2073.    decrc=rc
  2074.  
  2075.    if decrc >= UUcmdFail then do         /* should be a CATASTROPHIC ERROR */
  2076.       say '***** FATAL ERROR LEVEL for 'partname 'from file(s)' filestr
  2077.       say '***** exiting ....'  
  2078.       signal Cleanup                     /* QUIT - DO NOT CONTINUE         */
  2079.    end 
  2080.  
  2081.    if decrc>0 then do
  2082.       msg='*** Decode returned rc='decrc 'for 'partname 'from file(s)' filestr
  2083.       interpret SayCmd   
  2084.       Miscinfo.Filesptr.pptr.1=NO                   /* DECODE had errors  */
  2085.    end
  2086.  
  2087.    UUOutCnt=UUOutCnt+1
  2088.  
  2089.    Call FileNoteOut
  2090.  
  2091.    if chopflag=YES then do             /* delete ALL chopped inputs always*/
  2092.       Address Command 'Delete ' filein 'QUIET'
  2093.    end 
  2094.  
  2095. DecodeUUFilesEnd:
  2096.  
  2097. Return
  2098.  
  2099. /**************************************************************************/
  2100. /*                                                                        */
  2101. /*                Handle the Base64 encoded decoding.                     */
  2102. /*                                                                        */
  2103. /**************************************************************************/
  2104. Decode64Files:
  2105.  
  2106.    if scanonly=yes then signal Decode64FilesEnd
  2107.  
  2108.    B64cmdx=Base64cmd                             /* copy for replacement  */
  2109.  
  2110.    do j=1 to words(B64cmdx)
  2111.       select
  2112.         when upper(word(B64cmdx,j))='%SF' then do
  2113.            wptr=wordindex(B64cmdx,j)-1
  2114.            B64cmdx=delword(B64cmdx,j,1)
  2115.            B64cmdx=insert(filein,B64cmdx,wptr,length(filein)+1,' ')
  2116.         end
  2117.         when upper(word(B64cmdx,j))='%DF' then do
  2118.            wptr=wordindex(B64cmdx,j)-1
  2119.            B64cmdx=delword(B64cmdx,j,1)
  2120.            destfile='"'||dest||partname||'"'
  2121.            B64cmdx=insert(destfile,B64cmdx,wptr,length(destfile)+1,' ')
  2122.         end
  2123.         when upper(word(B64cmdx,j))='%SD' then do
  2124.            wptr=wordindex(B64cmdx,j)-1
  2125.            B64cmdx=delword(B64cmdx,j,1)
  2126.            B64cmdx=insert(source,B64cmdx,wptr,length(source)+1,' ')
  2127.         end
  2128.         when upper(word(B64cmdx,j))='%DD' then do
  2129.            wptr=wordindex(B64cmdx,j)-1
  2130.            B64cmdx=delword(B64cmdx,j,1)
  2131.            B64cmdx=insert(dest,B64cmdx,wptr,length(dest)+1,' ')
  2132.         end
  2133.         otherwise nop
  2134.       end
  2135.    end   
  2136.  
  2137.    Address Command B64cmdx 
  2138.    decrc=rc
  2139.  
  2140.    if decrc>=B64cmdFail then do
  2141.       say '***** FATAL ERROR LEVEL for 'partname 'from file(s)' filestr
  2142.       say '***** exiting ....'  
  2143.       signal Cleanup                     /* QUIT - DO NOT CONTINUE         */
  2144.    end
  2145.  
  2146.    if decrc>0 then do
  2147.       msg='*** Decode returned rc='decrc 'for 'partname 'from file(s)' filestr
  2148.       interpret SayCmd   
  2149.       Miscinfo.Filesptr.pptr.1=NO                   /* DECODE had errors  */
  2150.    end
  2151.  
  2152.    B64OutCnt=B64OutCnt+1
  2153.  
  2154.    Call FileNoteOut
  2155.  
  2156.    if chopflag=YES then do             /* delete ALL chopped inputs always*/
  2157.       Address Command 'Delete ' filein 'QUIET'
  2158.    end 
  2159.  
  2160. Decode64FilesEnd:
  2161.  
  2162. Return
  2163.  
  2164. /**************************************************************************/
  2165. /*                                                                        */
  2166. /*                Handle the BinHex encoded decoding.     !!! Added       */
  2167. /*                                                                        */
  2168. /**************************************************************************/
  2169. DecodeBHFiles:
  2170.  
  2171.    if scanonly=yes then signal DecodeBHFilesEnd
  2172.  
  2173.    Bincmdx=BinHexCmd                             /* copy for replacement  */
  2174.  
  2175.    sfpos=pos('%SF',upper(Bincmdx))
  2176.    do while sfpos>0
  2177.       Bincmdx=delstr(Bincmdx,sfpos,3)
  2178.       Bincmdx=insert(filein,Bincmdx,sfpos-1,length(filein),' ')
  2179.       sfpos=pos('%SF',upper(Bincmdx))
  2180.    end
  2181.  
  2182.    dfpos=pos('%DF',upper(Bincmdx))
  2183.    do while dfpos>0
  2184.       Bincmdx=delstr(Bincmdx,dfpos,3)
  2185.       destfile=dest||partname
  2186.       Bincmdx=insert(destfile,Bincmdx,dfpos-1,length(destfile),' ')
  2187.       dfpos=pos('%DF',upper(Bincmdx))
  2188.    end
  2189.  
  2190.    sdpos=pos('%SD',upper(Bincmdx))
  2191.    do while sdpos>0
  2192.       Bincmdx=delstr(Bincmdx,sdpos,3)
  2193.       Bincmdx=insert(source,Bincmdx,sdpos-1,length(source),' ')
  2194.       sdpos=pos('%SD',upper(Bincmdx))
  2195.    end
  2196.  
  2197.    ddpos=pos('%DD',upper(Bincmdx))
  2198.    do while ddpos>0
  2199.       Bincmdx=delstr(Bincmdx,ddpos,3)
  2200.       Bincmdx=insert(dest,Bincmdx,ddpos-1,length(dest),' ')
  2201.       ddpos=pos('%DD',upper(Bincmdx))
  2202.    end
  2203.  
  2204.    Address Command Bincmdx 
  2205.    decrc=rc
  2206.  
  2207.    if decrc>=BinCmdFail then do
  2208.       say '***** FATAL ERROR LEVEL for 'partname 'from file(s)' filestr
  2209.       say '***** exiting ....'  
  2210.       signal Cleanup                     /* QUIT - DO NOT CONTINUE         */
  2211.    end
  2212.  
  2213.    if decrc>0 then do
  2214.       msg='*** Decode returned rc='decrc 'for 'partname 'from file(s)' filestr
  2215.       interpret SayCmd   
  2216.       Miscinfo.Filesptr.pptr.1=NO                   /* DECODE had errors  */
  2217.    end
  2218.  
  2219.    BinOutCnt=BinOutCnt+1
  2220.  
  2221.    Call FileNoteOut
  2222.  
  2223.    if chopflag=YES then do             /* delete ALL chopped inputs always*/
  2224.       Address Command 'Delete ' filein 'QUIET'
  2225.    end 
  2226.  
  2227. DecodeBHFilesEnd:
  2228.  
  2229. Return
  2230.  
  2231. /**************************************************************************/
  2232. /*                                                                        */
  2233. /*  Chop Multi  files into pieces for decoding. Use startlines found prev.*/
  2234. /*                                                                        */
  2235. /**************************************************************************/
  2236. ChopFile:       
  2237.  
  2238.    goodopen=open('IN',filein,'R')
  2239.    if ~goodopen then do
  2240.       msg='(E) Error opening 'filein 'for chopping '
  2241.       interpret Saycmd
  2242.    end
  2243.  
  2244.    start=1                                       /* start with line 1     */
  2245.  
  2246.    do j=1 to Files.filesptr.1.0                  /* loop thru partnames   */
  2247.  
  2248. If Debug then say 'Chopping ' Files.filesptr ' into ' Files.filesptr.1.0 ' pieces'
  2249.  
  2250.       Miscinfo.Filesptr.j.1.1.1=YES           /* indicate file is chopped */ 
  2251.  
  2252.       if j=1 then start=1                        /* first entry           */
  2253.              else start=Files.filesptr.1.j.1.1.1
  2254.  
  2255.       if start=missing then do
  2256.          say 'Startline for ' Files.filesptr Files.filesptr.1.j 'is invalid ... exiting'
  2257.          exit
  2258.       end
  2259.  
  2260.       next=j+1
  2261.  
  2262.       if j=Files.filesptr.1.0 then stop=999999   /* last entry - no next  */
  2263.       else do
  2264.          stop=Files.filesptr.1.next.1.1.1
  2265.          if stop=missing then do
  2266.             say 'Stopline for ' Files.filesptr  Files.filesptr.1.next 'is invalid ... exiting'
  2267.             exit
  2268.          end
  2269.          stop=stop-1
  2270.       end
  2271.  
  2272.       if Miscinfo.Filesptr.j.1.1.1.1=missing then do
  2273.          fileout=DWtemp||Files.filesptr||'.'||j     /* build chopped name */
  2274.          goodopen=open('OUT',fileout,'W')
  2275.          if ~goodopen then do
  2276.             msg='(E) Error opening 'fileout 
  2277.             interpret Saycmd
  2278.          end
  2279.       end
  2280.  
  2281. If Debug then say '      Writing ... ' START STOP fileout 
  2282.  
  2283.       do k=start to stop                         /* read/write lines out  */
  2284.          linein=readln('IN')
  2285.          if ~eof('IN') then do
  2286.             if Miscinfo.Filesptr.j.1.1.1.1=missing then do
  2287.                result=writeln('OUT',linein)
  2288.             end 
  2289.          end 
  2290.          else do 
  2291.             k=stop                               /* EOF - quit looping    */
  2292.          end 
  2293.       end 
  2294.       if Miscinfo.Filesptr.j.1.1.1.1=missing then do
  2295.          result=close('OUT')                     /* close output file     */
  2296.       end
  2297.    end
  2298.  
  2299.    result=close('IN')
  2300.  
  2301. Return
  2302.  
  2303. /**************************************************************************/
  2304. /*                                                                        */
  2305. /*                    Report Decoding operations.                         */
  2306. /*                                                                        */
  2307. /**************************************************************************/
  2308. IssueDecodeMsg:
  2309.  
  2310.    msg=overlay(filestr,msg,length(msg)+3)
  2311.    if ShowDecode then interpret SayCmd
  2312.  
  2313. Return
  2314.  
  2315. /**************************************************************************/
  2316. /*                                                                        */
  2317. /*                Filenote output files as specified.                     */
  2318. /*                                                                        */
  2319. /* Handle escaping Amiga Special Characters. This requires an apostrophe  */
  2320. /* to be placed before #,%,? in filenames.                                */
  2321. /*                                                                        */
  2322. /**************************************************************************/
  2323. FileNoteOut:   
  2324.  
  2325.    foundspec=pos("'",partname)
  2326.    do while foundspec > 0
  2327.       part1=substr(partname,1,foundspec-1)
  2328.       part2=substr(partname,foundspec+1)
  2329.       partname=part1||"''"||part2
  2330.       foundspec=pos("'",part2) 
  2331.       if foundspec>0 then foundspec=foundspec+length(part1)+2
  2332.    end
  2333.  
  2334.    foundspec=pos("%",partname)
  2335.    do while foundspec > 0
  2336.       part1=substr(partname,1,foundspec-1)
  2337.       part2=substr(partname,foundspec+1)
  2338.       partname=part1||"''%"||part2
  2339.       foundspec=pos("%",part2) 
  2340.       if foundspec>0 then foundspec=foundspec+length(part1)+3
  2341.    end
  2342.  
  2343.    foundspec=pos("#",partname)
  2344.    do while foundspec > 0
  2345.       part1=substr(partname,1,foundspec-1)
  2346.       part2=substr(partname,foundspec+1)
  2347.       partname=part1||"''#"||part2
  2348.       foundspec=pos("#",part2) 
  2349.       if foundspec>0 then foundspec=foundspec+length(part1)+3
  2350.    end
  2351.  
  2352.    foundspec=pos("?",partname)
  2353.    do while foundspec > 0
  2354.       part1=substr(partname,1,foundspec-1)
  2355.       part2=substr(partname,foundspec+1)
  2356.       partname=part1||"''?"||part2
  2357.       foundspec=pos("?",part2) 
  2358.       if foundspec>0 then foundspec=foundspec+length(part1)+3
  2359.    end
  2360.  
  2361.    foundspec=pos("~",partname)
  2362.    do while foundspec > 0
  2363.       part1=substr(partname,1,foundspec-1)
  2364.       part2=substr(partname,foundspec+1)
  2365.       partname=part1||"''~"||part2
  2366.       foundspec=pos("~",part2) 
  2367.       if foundspec>0 then foundspec=foundspec+length(part1)+3
  2368.    end
  2369.   
  2370.    foundspec=pos("(",partname)
  2371.    do while foundspec > 0
  2372.       part1=substr(partname,1,foundspec-1)
  2373.       part2=substr(partname,foundspec+1)
  2374.       partname=part1||"''("||part2
  2375.       foundspec=pos("(",part2) 
  2376.       if foundspec>0 then foundspec=foundspec+length(part1)+3
  2377.    end
  2378.   
  2379.    foundspec=pos(")",partname)
  2380.    do while foundspec > 0
  2381.       part1=substr(partname,1,foundspec-1)
  2382.       part2=substr(partname,foundspec+1)
  2383.       partname=part1||"'')"||part2
  2384.       foundspec=pos(")",part2) 
  2385.       if foundspec>0 then foundspec=foundspec+length(part1)+3
  2386.    end
  2387.   
  2388.    if filenote~='' & Miscinfo.Filesptr.pptr.1.1=missing then do
  2389.       interpret intfnote fnote
  2390.       fnotex=substr(fnotex,1,79)
  2391.       fncmd="Address Command 'Filenote "||'"'||partname||'" "'||fnotex||'"'||" '"
  2392.       interpret fncmd
  2393.       fnrc=rc
  2394.       if fnrc>0 then do
  2395.          msg='*** Filenote returned rc='fnrc 'for 'partname 
  2396.          interpret SayCmd   
  2397.       end
  2398.       Miscinfo.Filesptr.pptr.1.1=YES             /* mark as filenoted     */
  2399.    end 
  2400.  
  2401. Return
  2402.  
  2403. /**************************************************************************/
  2404. /*                                                                        */
  2405. /*               Issue any Warning  messages we may have                  */
  2406. /*                                                                        */
  2407. /**************************************************************************/
  2408. IssueWarnings:
  2409.  
  2410.    if warnings.0>0 then do
  2411.       msg=' '
  2412.       interpret Saycmd
  2413.    end
  2414.    do j=1 to warnings.0
  2415.       msg=warnings.j
  2416.       interpret Saycmd
  2417.    end
  2418.  
  2419. Return
  2420.  
  2421. /**************************************************************************/
  2422. /*                                                                        */
  2423. /*               Convert Date: line in header to timestamp                */
  2424. /*                                                                        */
  2425. /**************************************************************************/
  2426. TimeStamp:
  2427.  
  2428.    datemsg=upper(datemsg)                       /* upper case it          */   
  2429.    if pos(',',datemsg)>0 then datemsg=substr(datemsg,pos(',',datemsg)+1)
  2430.    datemsg=strip(datemsg)    
  2431.   
  2432.    Call CalcDays
  2433.  
  2434. Return
  2435.  
  2436. /**************************************************************************/
  2437. /*                                                                        */
  2438. /*               Calculate a value for year+month+day                     */
  2439. /*                                                                        */
  2440. /**************************************************************************/
  2441. CalcDays:
  2442.  
  2443.    leap=0                                       /* assume not a leap year */
  2444.    year=word(datemsg,3)                         /* year portion of msg    */
  2445.    if year<100 then do                          /* fix 2 digit years      */
  2446.       sdate=date('S')                           /* yyyymmdd               */
  2447.       year=left(sdate,4)                        /* get just the yyyy part */
  2448.    end
  2449.    month=word(datemsg,2)                        /* month portion of msg   */
  2450.    day=word(datemsg,1)                          /* day portion of msg     */
  2451.    time=word(datemsg,4)                         /* time portion of msg    */
  2452.    offset=word(datemsg,5)                       /* offset from GMT        */
  2453.    parse var time hour ':' min ':' second       /* get time pieces        */
  2454.    Select
  2455.       when month='JAN' then month=0
  2456.       when month='FEB' then do        /* not worth the cycles for 2100AD  */   
  2457.          month=31
  2458.          if year//4=0 then leap=1               
  2459.       end
  2460.       when month='MAR' then month=59+leap       
  2461.       when month='APR' then month=90+leap
  2462.       when month='MAY' then month=120+leap
  2463.       when month='JUN' then month=151+leap
  2464.       when month='JUL' then month=181+leap
  2465.       when month='AUG' then month=212+leap
  2466.       when month='SEP' then month=243+leap
  2467.       when month='OCT' then month=273+leap
  2468.       when month='NOV' then month=304+leap
  2469.       when month='DEC' then month=334+leap
  2470.       otherwise do
  2471.          msg=' '
  2472.          interpret Saycmd
  2473.          msg='Date Error processing file' Files.i 
  2474.          interpret Saycmd
  2475.          msg='     ' datemsg
  2476.          interpret Saycmd
  2477.       end
  2478.    end
  2479.  
  2480.    days=day+month+(year*365)
  2481.  
  2482. Return
  2483.  
  2484. /**************************************************************************/
  2485. /*                                                                        */
  2486. /*               Do all of the basic initialization stuff.                */
  2487. /*                                                                        */
  2488. /**************************************************************************/
  2489. Init:
  2490.  
  2491.    Call ChangeDir                    /* Change to PROGDIR:                */
  2492.    Call InternalDefaults             /* init internal default values      */
  2493.    Call CmdOverrides                 /* load and test cmd line options    */
  2494.    Call ReadPrefs                    /* load and test PrefsFile options   */
  2495.    Call SetParms                     /* set values based on final options */
  2496.    Call LoadSecTab                   /* load Section: identifier info     */
  2497.    Call LoadBase64Types              /* load B64 start line indicators    */
  2498.    Call LoadBinTypes                 /* load binary types to handle       */
  2499.    Call LoadEncTypes                 /* load MIME encoding information    */
  2500.    Call EnsureLibs                   /* add necessary libs if needed      */
  2501.  
  2502.    if SkipFrom | DeleteFrom then Call LoadSkipFroms  /* load table        */ 
  2503.  
  2504.    if SkipSubject | DeleteSubject then Call LoadSkipSubjects 
  2505.  
  2506.    if (DumpOpts | Debug) then Call DumpOpts /* wants options list on rpt  */
  2507.  
  2508.    if Recursive then do                     /* Recursive=YES option       */ 
  2509.       Call Getdirs                          /* get directories            */
  2510.    end
  2511.  
  2512.    if (ShowDirs | Debug) then Call DumpDirs /* wants dir listing on rpt   */
  2513.  
  2514.    if verbose then do
  2515.       if show('L','rexxtricks.library') then do /* using trics library    */
  2516.          say time() 'Using rexxtricks.library ...'
  2517.       end
  2518.       else do                               
  2519.          say time() 'Using QuickSort ...'           
  2520.       end
  2521.    end
  2522.  
  2523. Return
  2524.  
  2525. /**************************************************************************/
  2526. /*                                                                        */
  2527. /*     Change directory to that of this program. Ensures that we find     */
  2528. /*                        all of the files we need                        */
  2529. /*                                                                        */
  2530. /**************************************************************************/
  2531. ChangeDir:
  2532.  
  2533.    
  2534.    Parse UPPER source invoked results called rest
  2535.     rest=subword(rest,1,words(rest)-2)
  2536.     slpos=lastpos('/',rest)
  2537.     copos=pos(':',rest)
  2538.     progdir=strip(substr(rest,1,max(slpos,copos)-1))
  2539.    origdir=pragma('D',progdir)
  2540.  
  2541. Return
  2542.  
  2543. /**************************************************************************/
  2544. /*                                                                        */
  2545. /*     These values are hard coded and can't be overridden                */
  2546. /*                                                                        */
  2547. /**************************************************************************/
  2548. InternalDefaults:
  2549.  
  2550.    YES=1                                           /* a few useful values */
  2551.    TRUE=1                                          /* a few useful values */
  2552.    ON=1                                            /* a few useful values */
  2553.    
  2554.    NO=0                                            /* a few useful values */
  2555.    FALSE=0                                         /* a few useful values */
  2556.    OFF=0                                           /* a few useful values */
  2557.  
  2558.    DONE=0                                          /* a few useful values */
  2559.  
  2560.    cr='0D'x                                        /* carriage return     */  
  2561.    tab='09'x                                       /* tab character value */
  2562.    dashes=copies('-',72)              /* dashed line for report divisions */
  2563.    missing='.'                                     /* var for array init  */
  2564.  
  2565.    infolines=18               /* top lines of this program used for intro */
  2566.    delaymsg.0=infolines                        /* startup lines - delayed */
  2567.    do i=1 to infolines                         
  2568.       delaymsg.i=sourceline(i)
  2569.    end
  2570.  
  2571.    intfnote='fnotex='               /* used for creating output filenotes */ 
  2572.  
  2573.    SayCmd='Say msg'                 /* write messages to console not Log  */
  2574.  
  2575.  
  2576. /**************************************************************************/
  2577. /*                                                                        */
  2578. /*     These values are used if not overridden by the Prefs file          */
  2579. /*                     or as command line arguments.                      */
  2580. /*                                                                        */
  2581. /**************************************************************************/
  2582.  
  2583. int.0=65
  2584. int.1 ='B64cmdFail        BF     N    20'
  2585. int.2 ='Base64Cmd         BC     F    Base64Decode %SF %DF USEMINLEN > nil:'
  2586. int.3 ='Base64TypesFile   B64F   F    DWdecode.Base64.Types'
  2587. int.4 ='BinCmdFail        BHF    N    20'
  2588. int.5 ='BinHexCmd         BHC    F    BHD data=%DF %SF' 
  2589. int.6 ='BinTypesFile      BTF    F    DWdecode.Binary.Types'
  2590. int.7 ='Debug             DB     B    NO'
  2591. int.8 ='DeleteAfter       DELA   B    NO'
  2592. int.9 ='DeleteDups        DELD   B    NO'
  2593. int.10='DeleteFrom        DELF   B    NO'
  2594. int.11='DeleteOld         DELO   B    NO'
  2595. int.12='DeleteSubject     DELS   B    NO'
  2596. int.13='DeleteText        DELT   B    NO'
  2597. int.14='Dest              D      F    . '
  2598. int.15='DumpBase64Types   D64T   B    NO'        
  2599. int.16='DumpBinTypes      DBT    B    NO'
  2600. int.17='DumpDates         DD     B    NO'        
  2601. int.18='DumpEncTypes      DET    B    NO'
  2602. int.19='DumpFiles         DF     B    NO'        
  2603. int.20='DumpFroms         DFR    B    NO'        
  2604. int.21='DumpMisc          DM     B    NO'        
  2605. int.22='DumpOpts          DO     B    NO'
  2606. int.23='DumpPhase2        DP2    B    NO'        
  2607. int.24='DumpSectionTypes  DST    B    NO'
  2608. int.25='DumpSkipFroms     DSF    B    NO'        
  2609. int.26='DumpSkipSubjects  DSS    B    NO'        
  2610. int.27='DumpSubjects      DS     B    NO'
  2611. int.28='DWassignIN        DWI    S    DW:' 
  2612. int.29='DWtemp            DWT    F    T:'
  2613. int.30='EncTypesFile      ETF    F    DWdecode.Encode.Types'
  2614. int.31='FileNote          FN     S    %LLQ2 : %SUBJECT'
  2615. int.32='KeepDays          KD     N    30'
  2616. int.33='Log               L      B    YES'
  2617. int.34='LogFile           LF     S    DWdecode.Log'
  2618. int.35='MarkOld           MO     B    YES'
  2619. int.36='MaxHeader         MH     N    25'
  2620. int.37='MinEncoded        ME     N    4'
  2621. int.38='PrefsFile         P      F    DWdecode.Prefs'
  2622. int.39='Quiet             Q      B    NO'
  2623. int.40='Recursive         REC    B    YES'
  2624. int.41='Replace           REP    B    NO' 
  2625. int.42='RunBack           RB     S    run > nil:'
  2626. int.43='ScanOnly          SO     B    NO'
  2627. int.44='ScanProg          SP     F    FlashFind'
  2628. int.45='SectionTypesFile  STF    F    DWdecode.Section.Types'
  2629. int.46='ShowDecode        SHDE   B    YES'
  2630. int.47='ShowDirs          SHDI   B    YES'
  2631. int.48='ShowFiles         SHF    B    YES'
  2632. int.49='ShowParts         SHP    B    YES'
  2633. int.50='ShowStats         SHS    B    YES'
  2634. int.51='SkipFrom          SF     B    YES'
  2635. int.52='SkipFromFile      SFF    F    DWdecode.Skip.Froms'
  2636. int.53='SkipSubject       SS     B    YES'
  2637. int.54='SkipSubjectFile   SSF    F    DWdecode.Skip.Subjects'
  2638. int.55='Source            S      F    . '
  2639. int.56='TrapAllBegs       TAB    B    NO' 
  2640. int.57='TrapAllEncs       TAE    B    NO'         
  2641. int.58='TrapAllSecs       TAS    B    NO'     
  2642. int.59='TrapNewEncs       TNE    B    YES'         
  2643. int.60='TrapNewEncsFile   TNEF   S    DWdecode.Trap.Encodes'
  2644. int.61='TrapNewSecs       TNS    B    YES'
  2645. int.62='TrapNewSecsFile   TNSF   S    DWdecode.Trap.Sections'
  2646. int.63='UUcmd             UC     F    UUout %SF BUFSIZE=150 IGNORETERMINATION USEBASENAME > nil:'
  2647. int.64='UUcmdFail         UF     N    10'
  2648. int.65='XDELETE           XD     B    NO'
  2649.  
  2650.  
  2651.    cmd.0=int.0                             /* duplicate number of entires */   
  2652.  
  2653.    do i=1 to int.0                         /* loop through them           */
  2654.       cmd.i    =word(int.i,1)              /* variable name in program    */
  2655.       cmd.i.1  =word(int.i,2)              /* an alias for variable name  */ 
  2656.       cmd.i.1.1=word(int.i,3)              /* type of variable B,S,T,F,N  */
  2657.       cmd.i.1.1.1=subword(int.i,4)         /* default for the variable    */
  2658.       if cmd.i.1.1='N' | cmd.i.1.1='B' then cmdstr=cmd.i||"="||cmd.i.1.1.1 
  2659.       else cmdstr=cmd.i||"='"||cmd.i.1.1.1||"'" /* build variable assign  */ 
  2660.       interpret cmdstr                     /* do it                       */
  2661.    end
  2662.  
  2663.    drop int.                               /* done with this array        */
  2664.  
  2665. Return
  2666.  
  2667. /**************************************************************************/
  2668. /*                                                                        */
  2669. /*           See what values are specified on the command line.           */
  2670. /*          These will override the values in the default file.           */
  2671. /*                                                                        */
  2672. /**************************************************************************/
  2673. /* Load all arguments that have '=' signs in them. Parse strings based on */
  2674. /* assuming a beginning quote (either type) and locating the ending one.  */
  2675. /* After deleting ALL xxx=yyy type pieces, the remaining ones SHOULD be   */
  2676. /* boolean switches. All of the commands will be tested based upon the    */
  2677. /* type value in the cmd. array. Strings can be anything; Files must      */
  2678. /* already exist; Booleans must be 1/0, YES/NO, ON/OFF; and Numerics must */
  2679. /* be numeric. Any that don't match a valid command or its alias are      */
  2680. /* reported as errors and we exit after all have been processed.          */
  2681. /*                                                                        */
  2682. /**************************************************************************/
  2683. /* If help requested then display internal defaults and exit.             */
  2684. /**************************************************************************/
  2685. CmdOverrides:
  2686.  
  2687.    if commandline='?' | upper(commandline)='-H' | upper(commandline)='HELP' then do
  2688.       do i=1 to delaymsg.0
  2689.          msg=delaymsg.i
  2690.          interpret Saycmd   
  2691.       end
  2692.       msg=' '
  2693.       interpret Saycmd
  2694.       msg='Command-Option   Alias  Internal Value'
  2695.       interpret Saycmd
  2696.       msg=left(dashes,78)
  2697.       interpret Saycmd
  2698.       do i=1 to cmd.0
  2699.          msg=cmd.i
  2700.          msg=overlay(cmd.i.1,msg,18)
  2701.          msg=overlay(cmd.i.1.1.1,msg,25)
  2702.          interpret Saycmd
  2703.       end 
  2704.       msg=' '
  2705.       interpret Saycmd
  2706.       msg='See DWDecode.doc or DWDecode.guide for complete description of options'
  2707.       interpret Saycmd
  2708.       signal cleanup
  2709.    end
  2710.  
  2711.    say ' '
  2712.    say time() 'Determining runtime options ...'
  2713.  
  2714.    cmdopt.=missing      
  2715.    cmdopt.0=0
  2716.  
  2717.    eqpos=pos('=',commandline)
  2718.    i=0
  2719.    quitflag=NO
  2720.  
  2721.    do while eqpos~=0
  2722.       cmdpart1=strip(substr(commandline,1,eqpos-1))
  2723.       cmdpart2=strip(substr(commandline,eqpos+1))
  2724.       i=i+1
  2725.       cmdopt.0=i
  2726.       cmdopt.i=word(cmdpart1,words(cmdpart1))
  2727.       cmdpart1=subword(cmdpart1,1,words(cmdpart1)-1)
  2728.       select
  2729.          when substr(cmdpart2,1,1)='"' then do
  2730.             endquote=pos('"',cmdpart2,2)
  2731.             if endquote=0 then do
  2732.                delaymsg.0=delaymsg.0 + 1
  2733.                dx=delaymsg.0
  2734.                delaymsg.dx='(E) Missing ending quote for: ' cmdopt.i
  2735.                quitflag=YES
  2736.             end
  2737.             cmdopt.i.1=substr(cmdpart2,2,endquote-2)
  2738.             cmdpart2=substr(cmdpart2,endquote+1)
  2739.          end   
  2740.          when substr(cmdpart2,1,1)="'" then do
  2741.             endquote=pos("'",cmdpart2,2)
  2742.             if endquote=0 then do
  2743.                delaymsg.0=delaymsg.0 + 1
  2744.                dx=delaymsg.0
  2745.                delaymsg.dx='(E) Missing ending quote for: ' cmdopt.i
  2746.                quitflag=YES
  2747.             end
  2748.             cmdopt.i.1=substr(cmdpart2,2,endquote-2)
  2749.             cmdpart2=substr(cmdpart2,endquote+1)
  2750.          end
  2751.          otherwise do
  2752.             cmdopt.i.1=word(cmdpart2,1)
  2753.             cmdpart2=subword(cmdpart2,2)
  2754.          end
  2755.       end
  2756.       commandline=cmdpart1||' '||cmdpart2
  2757.       eqpos=pos('=',commandline)
  2758.    end
  2759.  
  2760.    do j=1 to words(commandline)
  2761.       i=i+1
  2762.       cmdopt.0=i 
  2763.       cmdopt.i=word(commandline,1)
  2764.       commandline=subword(commandline,2)
  2765.    end 
  2766.  
  2767.    do i=1 to cmdopt.0
  2768.       matchflag=NO
  2769.       do j=1 to cmd.0
  2770.          UPO=upper(cmdopt.i)
  2771.          UPV=upper(cmdopt.i.1)
  2772.          UPC=upper(cmd.j)
  2773.          UPA=upper(cmd.j.1)
  2774.          UPT=upper(cmd.j.1.1)
  2775.          if UPO=UPC | UPO=UPA then do
  2776.             matchflag=YES
  2777.             select
  2778.                when UPT='B' then do
  2779.                   select
  2780.                      when UPV=missing then cmdopt.i.1='YES'
  2781.                      when UPV='YES'   then nop
  2782.                      when UPV='ON'    then nop
  2783.                      when UPV='TRUE'  then nop
  2784.                      when UPV='1'     then nop
  2785.                      when UPV='NO'    then nop
  2786.                      when UPV='OFF'   then nop
  2787.                      when UPV='FALSE' then nop
  2788.                      when UPV='0'     then nop
  2789.                      otherwise do
  2790.                         delaymsg.0=delaymsg.0 + 1
  2791.                         dx=delaymsg.0
  2792.                         delaymsg.dx='(E) Invalid value for 'UPC 'must be YES/NO'
  2793.                         quitflag=YES
  2794.                      end
  2795.                   end
  2796.                end
  2797.                when UPT='N' then do
  2798.                   if verify(UPV,'0123456789')~=0 then do
  2799.                      say '(E) Invalid value for 'UPC 'must be numeric'
  2800.                      quitflag=YES
  2801.                   end
  2802.                end
  2803.                otherwise nop
  2804.             end 
  2805.             cmdopt.i=cmd.j                     /* store real variable name   */
  2806.             cmdopt.i.1.1=cmd.j.1.1             /* store variable type        */
  2807.             leave j
  2808.          end
  2809.       end
  2810.       if ~matchflag then do
  2811.          delaymsg.0=delaymsg.0 + 1
  2812.          dx=delaymsg.0
  2813.          delaymsg.dx='(E) Unrecognized argument: 'UPO'. See Documentation.'
  2814.          quitflag=YES
  2815.       end 
  2816.    end
  2817.  
  2818. /**************************************************************************/
  2819. /* Set values from command line, will have to do it again, after values   */
  2820. /* are set from PrefsFile. Makes it easier to use cmdline options early.  */
  2821. /**************************************************************************/
  2822.    do i=1 to cmdopt.0                      /* loop through them           */
  2823.       if cmdopt.i.1.1='N' | cmdopt.i.1.1='B' then cmdstr=cmdopt.i||"="||cmdopt.i.1 
  2824.       else cmdstr=cmdopt.i||"='"||cmdopt.i.1||"'"   /* build var assign   */ 
  2825.       interpret cmdstr                     /* do it                       */
  2826.    end
  2827.  
  2828. Return
  2829.  
  2830. /**************************************************************************/
  2831. /*                                                                        */
  2832. /*            Read in the information from the Prefs file                 */
  2833. /*                                                                        */
  2834. /**************************************************************************/
  2835. ReadPrefs:
  2836.  
  2837.    pcmd.=missing
  2838.    i=0
  2839.  
  2840.    goodopen=open('Prefs',PrefsFile,'R')
  2841.    if ~goodopen then do
  2842.       delaymsg.0=delaymsg.0 + 1
  2843.       dx=delaymsg.0
  2844.       delaymsg.dx='(W) Prefs file not found - using command options & internal values'
  2845.    end
  2846.    else do
  2847.       delaymsg.0=delaymsg.0 + 1
  2848.       dx=delaymsg.0
  2849.       delaymsg.dx='Using PrefsFile:         ' PrefsFile
  2850.       do until eof('Prefs')
  2851.          default=readln('Prefs')
  2852.          if default~=' ' & default~='#' & default~='' then do
  2853.             if pos('#',default)~=1 then do
  2854.                if pos('#',default)>2 then do
  2855.                   default=substr(default,1,pos('#',default)-1)
  2856.                end
  2857.                default=strip(default)
  2858.                select
  2859.                   when pos('=',default)>0 then do
  2860.                      i=i+1
  2861.                      pcmd.i=substr(default,1,pos('=',default)-1)
  2862.                      pval=substr(default,pos('=',default)+1)
  2863.                      pval=strip(pval,'B',"'") 
  2864.                      pval=strip(pval,'B','"') 
  2865.                      pcmd.i.1=pval
  2866.                   end
  2867.                   when words(default)=1 then do
  2868.                      i=i+1
  2869.                      pcmd.i=default
  2870.                      pcmd.i.1='YES'
  2871.                   end 
  2872.                   otherwise do
  2873.                      delaymsg.0=1+delaymsg.0 
  2874.                      dx=delaymsg.0
  2875.                      delaymsg.dx='(E) Missing "=" in PrefsFile line: 'default
  2876.                      quitflag=YES
  2877.                   end 
  2878.                end
  2879.             end
  2880.          end
  2881.       end
  2882.    end
  2883.  
  2884.    result=close('Prefs')
  2885.  
  2886.    pcmd.0=i                               /* number of PrefsFile options  */
  2887.  
  2888. /**************************************************************************/
  2889. /*         Validate options set in the Preferences file.                  */
  2890. /**************************************************************************/
  2891.  
  2892.    do i=1 to pcmd.0
  2893.       matchflag=NO
  2894.       do j=1 to cmd.0
  2895.          UPO=upper(pcmd.i)
  2896.          UPV=upper(pcmd.i.1)
  2897.          UPC=upper(cmd.j)
  2898.          UPA=upper(cmd.j.1)
  2899.          UPT=upper(cmd.j.1.1)
  2900.          if UPO=UPC | UPO=UPA then do
  2901.             matchflag=YES
  2902.             select
  2903.                when UPT='B' then do
  2904.                   select
  2905.                      when UPV=missing then pcmd.i.1='YES'
  2906.                      when UPV='YES'   then nop
  2907.                      when UPV='ON'    then nop
  2908.                      when UPV='TRUE'  then nop
  2909.                      when UPV='1'     then nop
  2910.                      when UPV='NO'    then nop
  2911.                      when UPV='OFF'   then nop
  2912.                      when UPV='FALSE' then nop
  2913.                      when UPV='0'     then nop
  2914.                      otherwise do
  2915.                         delaymsg.0=delaymsg.0 + 1
  2916.                         dx=delaymsg.0
  2917.                         delaymsg.dx='(E) Invalid value for 'UPC 'must be YES/NO'
  2918.                         quitflag=YES
  2919.                      end
  2920.                   end
  2921.                end
  2922.                when UPT='N' then do
  2923.                   if verify(UPV,'0123456789')~=0 then do
  2924.                      say '(E) Invalid value for 'UPC 'must be numeric'
  2925.                      quitflag=YES
  2926.                   end
  2927.                end
  2928.                otherwise nop
  2929.             end 
  2930.             pcmd.i=cmd.j                        /* store real variable name   */
  2931.             pcmd.i.1.1=cmd.j.1.1                /* store variable type        */
  2932.             leave j
  2933.          end
  2934.       end
  2935.       if ~matchflag then do
  2936.          delaymsg.0=delaymsg.0 + 1
  2937.          dx=delaymsg.0
  2938.          delaymsg.dx='(E) Unrecognized argument: 'UPO'. See Documentation.'
  2939.          quitflag=YES
  2940.       end 
  2941.    end
  2942.  
  2943.    do i=1 to pcmd.0                        /* loop through them           */
  2944.       if pcmd.i.1.1='N' | pcmd.i.1.1='B' then cmdstr=pcmd.i||"="||pcmd.i.1 
  2945.       else cmdstr=pcmd.i||"='"||pcmd.i.1||"'"   /* build variable assign  */ 
  2946.       interpret cmdstr                     /* do it                       */
  2947.    end
  2948.  
  2949.    drop pcmd.                                   /* done with this array   */
  2950.  
  2951. /**************************************************************************/
  2952. /*         Set values from command line for final time.                   */
  2953. /**************************************************************************/
  2954.  
  2955.    do i=1 to cmdopt.0                      /* loop through them           */
  2956.       if cmdopt.i.1.1='N' | cmdopt.i.1.1='B' then cmdstr=cmdopt.i||"="||cmdopt.i.1 
  2957.       else cmdstr=cmdopt.i||"='"||cmdopt.i.1||"'"   /* build var assign   */ 
  2958.       interpret cmdstr                     /* do it                       */
  2959.    end
  2960.  
  2961.    drop cmdopt.                                 /* done with this array   */
  2962.  
  2963.    if DEBUG=YES then QUIET=NO             /* turn on all messages         */
  2964.    if QUIET=NO then VERBOSE=YES           /* Make into a positive remark  */
  2965.                else VERBOSE=NO
  2966.  
  2967.    if verbose then say time() 'Verifying existence of files ...'
  2968.  
  2969.    do i=1 to cmd.0                        /* loop thru validating files   */
  2970.       if cmd.i.1.1='F' then do
  2971.          tstr='tfile=word('||cmd.i||',1)'
  2972.          interpret tstr
  2973.          if ~exists(tfile) then do 
  2974.             delaymsg.0=delaymsg.0 + 1
  2975.             dx=delaymsg.0
  2976.             delaymsg.dx='(E) File' tfile 'does not exist '  
  2977.             quitflag=YES
  2978.          end
  2979.       end
  2980.    end
  2981.  
  2982.    if Log=YES then do
  2983.       Saycmd="result=writeln('LOG',msg)"
  2984.       goodopen=open('LOG',logfile,'W')
  2985.       if ~goodopen then do
  2986.          delaymsg.0=1+delaymsg.0 
  2987.          dx=delaymsg.0
  2988.          delaymsg.dx='(E) Unable to open logfile:' logfile
  2989.          delaymsg.0=1+delaymsg.0
  2990.          dx=delaymsg.0
  2991.          delaymsg.dx='Continuing without logfile. Messages displaying on console'
  2992.          SayCmd='Say msg'
  2993.       end
  2994.    end
  2995.  
  2996.    do i=1 to delaymsg.0
  2997.       msg=delaymsg.i
  2998.       interpret Saycmd   
  2999.    end
  3000.  
  3001.    drop delaymsg.                               /* done with this array   */
  3002.  
  3003.    if quitflag then do                          /* command/prefs error(s) */  
  3004.       if Log=YES then do 
  3005.          Say ' '
  3006.          Say 'Unable to continue: See 'logfile 'for additional messages'
  3007.       end
  3008.       exit 20
  3009.    end
  3010.  
  3011. Return
  3012.  
  3013. /**************************************************************************/
  3014. /*                                                                        */
  3015. /*           Adjust options based on final values of variables            */
  3016. /*                                                                        */
  3017. /**************************************************************************/
  3018. SetParms:
  3019.  
  3020.    if Source='' then do
  3021.       msg='(E) SOURCE directory is a REQUIRED parameter. See documentation.'
  3022.       interpret Saycmd
  3023.       exit
  3024.    end
  3025.    if Dest='' then do
  3026.       msg='(E) DEST directory is a REQUIRED parameter. See documentation.'
  3027.       interpret Saycmd
  3028.       exit
  3029.    end
  3030.  
  3031.    dircnt=1                                  /* next directory to process */
  3032.    dirlist.0=1                                   /* one directory for now */
  3033.    if right(dest,1)~='/' & right(dest,1)~=':' then dest=dest||'/'
  3034.    if right(source,1)~='/' & right(source,1)~=':' then source=source||'/'
  3035.    dirlist.1=source                     /* the original source directory  */
  3036.  
  3037.    if MarkOld | DeleteOld then do               /* need a value for today */
  3038.       datemsg= date() ' ' time() ' +900'        /* build a fake Date:     */
  3039.       datemsg=upper(datemsg)                    /* force to upper for rtn */         
  3040.       Call CalcDays
  3041.       today=days
  3042.       if KeepDays<1 then do
  3043.          msg='(W) KeepDays less than 1. Forcing to KEEPDAYS=30'
  3044.          interpret Saycmd
  3045.          KeepDays=30
  3046.       end
  3047.    end 
  3048.  
  3049.    if XDELETE then do                          /* turn on ALL delete opts */
  3050.       DeleteAfter   =YES
  3051.       DeleteDups    =YES
  3052.       DeleteFrom    =YES
  3053.       DeleteOld     =YES
  3054.       DeleteSubject =YES
  3055.       DeleteText    =YES
  3056.    end
  3057.  
  3058. Return
  3059.  
  3060. /**************************************************************************/
  3061. /*                                                                        */
  3062. /*                           Load SECTION table                           */
  3063. /*                                                                        */
  3064. /*  Load tables for parsing partname, partnum information from external   */
  3065. /*  tables. Descriptions are in each and each is required.                */
  3066. /*                                                                        */
  3067. /**************************************************************************/
  3068. LoadSecTab:
  3069.  
  3070.    goodopen=open('SecTables',SectionTypesFile,'R')
  3071.    if ~goodopen then do
  3072.       msg='(E) Required file ('SectionTypesFile') not found. See documentation.'
  3073.       interpret Saycmd
  3074.       exit
  3075.    end
  3076.    msg='Using Section Types File:' SectionTypesFile
  3077.    if ~DEBUG & ~DUMPOPTS then interpret Saycmd
  3078.    i=0                                           /* array pointer         */
  3079.    do until eof('SecTables')
  3080.       SecTable=readln('SecTables')
  3081.       if SecTable~=' ' & SecTable~='#' & SecTable~='' then do
  3082.          if pos('#',SecTable) ~= 1 then do
  3083.             if pos('#',SecTable)>1 then do
  3084.                SecTable=substr(SecTable,1,pos('#',SecTable)-1)
  3085.             end
  3086.             SecTable=strip(SecTable)
  3087.             i=i+1                                /* bump array pointer    */
  3088.             j=word(SecTable,1)                   /* number of keys present*/
  3089.             Sectiontypes.i=j                     /* load array with value */
  3090.             l=2                                  /* first key portion     */
  3091.             do k=1 to j                          /* loop thru pairs       */
  3092.               Sectiontypes.i.k=word(SecTable,l)       /* key portion      */
  3093.               Sectiontypes.i.k.k=word(SecTable,l+1)   /* key location     */
  3094.               l=l+2                                   /* set to next pair */
  3095.             end
  3096.             Sectiontypes.i.1.1.1=word(SecTable,l)      /* part number     */ 
  3097.             Sectiontypes.i.1.1.1.1=word(SecTable,l+1)   /* total parts    */
  3098.             Sectiontypes.i.1.1.1.1.1=word(SecTable,l+2)  /* filename      */
  3099.             Sectiontypes.i.1.1.1.1.1.1=word(SecTable,l+3) /* sep. char.   */
  3100.          end
  3101.       end
  3102.    end
  3103.  
  3104.    Sectiontypes.0=i                              /* num in section table */
  3105.    result=close('SecTables')
  3106.  
  3107. Return
  3108.  
  3109. /**************************************************************************/
  3110. /*                                                                        */
  3111. /*        Get the different start line indicators for Base64 files.       */
  3112. /*                                                                        */
  3113. /**************************************************************************/
  3114. LoadBase64Types:
  3115.  
  3116.    goodopen=open('Base64Types',Base64TypesFile,'R')
  3117.    if ~goodopen then do
  3118.       msg='(E) Required file ('Base64TypesFile') not found. See documentation.'
  3119.       interpret Saycmd
  3120.       exit
  3121.    end
  3122.    msg='Using Base64 Types File: ' Base64TypesFile
  3123.    if ~DEBUG & ~DUMPOPTS then interpret Saycmd
  3124.    i=0
  3125.    do until eof('Base64Types')
  3126.       Base64type=readln('Base64Types')
  3127.       Base64type=strip(Base64type)
  3128.       if substr(Base64type,1,1)='#' | Base64type='' | Base64type=' ' then nop
  3129.       else do
  3130.          if pos('#',Base64type)>1 then do
  3131.             Base64type=substr(Base64type,1,pos('#',Base64type)-1)
  3132.             Base64type=strip(Base64type)
  3133.          end
  3134.          i=i+1
  3135.          Base64Types.i=Base64Type
  3136.       end
  3137.    end
  3138.    Base64Types.0=i
  3139.  
  3140.    result=close('Base64Types')
  3141.  
  3142. Return
  3143.  
  3144. /**************************************************************************/
  3145. /*                                                                        */
  3146. /*        Get the types of file extensions we're to try to handle         */
  3147. /*                                                                        */
  3148. /**************************************************************************/
  3149. LoadBinTypes:
  3150.  
  3151.    goodopen=open('BinTypes',BinTypesFile,'R')
  3152.    if ~goodopen then do
  3153.       msg='(E) Required file ('BinTypesFile') not found. See documentation.'
  3154.       interpret Saycmd
  3155.       exit
  3156.    end
  3157.    msg='Using Binary Types File: ' BinTypesFile
  3158.    if ~DEBUG & ~DUMPOPTS then interpret Saycmd
  3159.    i=0
  3160.    do until eof('BinTypes')
  3161.       bintype=readln('BinTypes')
  3162.       bintype=strip(bintype)
  3163.       if substr(bintype,1,1)='#' | bintype='' | bintype=' ' then nop
  3164.       else do
  3165.          if pos('#',bintype)>1 then do
  3166.             bintype=substr(bintype,1,pos('#',bintype)-1)
  3167.             bintype=strip(bintype)
  3168.          end
  3169.          i=i+1
  3170.          Bintypes.i=upper(bintype)
  3171.       end
  3172.    end
  3173.    Bintypes.0=i
  3174.  
  3175.    result=close('BinTypes')
  3176.  
  3177. Return
  3178.  
  3179. /**************************************************************************/
  3180. /*                                                                        */
  3181. /*     Get the MIME encoding types that are known and which they are      */
  3182. /*                                                                        */
  3183. /**************************************************************************/
  3184. LoadEncTypes:
  3185.  
  3186.    goodopen=open('EncTypes',EncTypesFile,'R')
  3187.    if ~goodopen then do
  3188.       msg='(E) Required file ('EncTypesFile') not found. See documentation.'
  3189.       interpret Saycmd
  3190.       exit
  3191.    end
  3192.    msg='Using Encode Types File: ' EncTypesFile
  3193.    if ~DEBUG & ~DUMPOPTS then interpret Saycmd
  3194.    i=0
  3195.    do until eof('EncTypes')
  3196.       enctype=readln('EncTypes')
  3197.       enctype=strip(enctype)
  3198.       if substr(enctype,1,1)='#' | enctype='' | enctype=' ' then nop
  3199.       else do
  3200.          if pos('#',enctype)>1 then do
  3201.             enctype=substr(enctype,1,pos('#',enctype)-1)
  3202.             enctype=strip(enctype)
  3203.          end
  3204.          i=i+1
  3205.          Enctypes.i=upper(word(enctype,1))
  3206.          if words(enctype)>1 then Enctypes.i.1=upper(word(enctype,2))
  3207.                              else Enctypes.i.1=missing
  3208.       end
  3209.    end
  3210.    Enctypes.0=i
  3211.  
  3212.    result=close('EncTypes')
  3213.  
  3214. Return
  3215.  
  3216. /**************************************************************************/
  3217. /*                                                                        */
  3218. /*        Load list of users in From: lines to SKIP                       */
  3219. /*                                                                        */
  3220. /**************************************************************************/
  3221. LoadSkipFroms:       
  3222.  
  3223.    goodopen=open('SkipFroms',SkipFromFile,'R')
  3224.    if ~goodopen then do
  3225.       msg=' '
  3226.       interpret Saycmd
  3227.       msg='(E) Unable to open SkipFromFile "'SkipFromFile'"' 
  3228.       interpret Saycmd
  3229.       msg='    Setting DELETEFROM=NO SKIPFROM=NO DUMPSKIPFROMS=NO'
  3230.       interpret Saycmd
  3231.       SkipFrom=NO
  3232.       DeleteFrom=NO
  3233.       DumpSkipFroms=NO
  3234.    end
  3235.    else do
  3236.       msg='Using SkipFromFile:      ' SkipFromFile   
  3237.       if ~DEBUG & ~DUMPOPTS then interpret Saycmd
  3238.    end
  3239.    i=0
  3240.    if goodopen then do until eof('SkipFroms')
  3241.       skipuser=readln('SkipFroms')
  3242.       skipuser=strip(skipuser)
  3243.  
  3244.       if substr(skipuser,1,1)='#' | skipuser='' | skipuser=' ' then nop
  3245.       else do
  3246.          i=i+1
  3247.          SkipFroms.i=skipuser
  3248.       end
  3249.    end
  3250.    SkipFroms.0=i 
  3251.  
  3252.    result=close('SkipFroms')
  3253.  
  3254. Return
  3255.  
  3256. /**************************************************************************/
  3257. /*                                                                        */
  3258. /*        Load list of words in Subject: lines to SKIP                    */
  3259. /*                                                                        */
  3260. /**************************************************************************/
  3261. LoadSkipSubjects:       
  3262.  
  3263.    goodopen=open('SkipSubjects',SkipSubjectFile,'R')
  3264.    if ~goodopen then do
  3265.       msg=' '
  3266.       interpret Saycmd
  3267.       msg='(E) Unable to open SkipSubjectFile "'SkipSubjectFile'"' 
  3268.       interpret Saycmd
  3269.       msg='    Setting DELETESUBJECT=NO SKIPSUBJECT=NO DUMPSKIPSUBJECTS=NO'
  3270.       interpret Saycmd
  3271.       SkipSubject=NO
  3272.       DeleteSubject=NO
  3273.       DumpSkipSubjects=NO
  3274.    end
  3275.    else do
  3276.       msg='Using SkipSubjectFile:   ' SkipSubjectFile   
  3277.       if ~DEBUG & ~DUMPOPTS then interpret Saycmd
  3278.    end
  3279.    i=0
  3280.    if goodopen then do until eof('SkipSubjects')
  3281.       skipuser=readln('SkipSubjects')
  3282.       skipuser=strip(skipuser)
  3283.  
  3284.       if substr(skipuser,1,1)='#' | skipuser='' | skipuser=' ' then nop
  3285.       else do
  3286.          i=i+1
  3287.          SkipSubjects.i=skipuser
  3288.       end
  3289.    end
  3290.    SkipSubjects.0=i 
  3291.  
  3292.    result=close('SkipSubjects')
  3293.  
  3294. Return
  3295.  
  3296. /**************************************************************************/
  3297. /*                                                                        */
  3298. /*              Make sure that we have all the libs we need:              */
  3299. /*                                                                        */
  3300. /*                               RexxSupport                              */
  3301. /*                               RexxArpLib                               */
  3302. /*                               QuickSort                                */
  3303. /*                                                                        */
  3304. /**************************************************************************/
  3305. EnsureLibs:
  3306.  
  3307.     goodlibs=TRUE
  3308.  
  3309.    if ~show('L','rexxsupport.library') then do
  3310.       if exists('LIBS:rexxsupport.library') then do 
  3311.             addlib('rexxsupport.library',0,-30) 
  3312.         end
  3313.         else do
  3314.           msg='(E) Unable to add rexxsupport.library -- check installation instructions'
  3315.           interpret Saycmd
  3316.             say msg
  3317.          goodlibs=FALSE
  3318.       end
  3319.    end
  3320.  
  3321.    if ~show('L','rexxarplib.library') then do
  3322.       if exists('LIBS:rexxarplib.library') then do
  3323.              addlib('rexxarplib.library',0,-30)
  3324.         end
  3325.         else do
  3326.           msg='(E) Unable to add rexxarplib.library -- check installation instructions'
  3327.           interpret Saycmd
  3328.             say msg
  3329.          goodlibs=FALSE
  3330.       end
  3331.    end
  3332.  
  3333.    if ~show('P','QuickSortPort') then do
  3334.       address command runback " quicksort"
  3335.       do i = 1 to 10
  3336.          if ~show('P','QuickSortPort') then call delay 20
  3337.          else leave i
  3338.       end
  3339.    end
  3340.  
  3341.    if show('P','QuickSortPort') then do
  3342.       call addlib('QuickSortPort',-30)
  3343.    end
  3344.    else do
  3345.       msg='(E) Unable to find QuickSort -- check installation instructions'
  3346.          interpret Saycmd
  3347.       say msg
  3348.       goodlibs=FALSE
  3349.    end
  3350.  
  3351.    if ~goodlibs then signal Cleanup        /* exit due to errors          */
  3352.  
  3353. Return
  3354.  
  3355.  
  3356. /**************************************************************************/
  3357. /*                                                                        */
  3358. /*          Read Source Directory for list directories to process         */
  3359. /*                                                                        */
  3360. /* force '/' onto source if not present and not a volume or assign        */
  3361. /*                                                                        */
  3362. /**************************************************************************/
  3363. GetDirs:
  3364.  
  3365.    tempdirs.=missing
  3366.    tempdirs.0 = FILELIST(source||'*',tempdirs,"D","E")
  3367.  
  3368.    do i=1 to tempdirs.0
  3369.       dirlist.0=1+dirlist.0
  3370.       dirptr=dirlist.0
  3371.       dirlist.dirptr=tempdirs.i||'/'      
  3372.    end
  3373.  
  3374.    dircnt=dircnt+1                               /* next dir to process   */
  3375.  
  3376.    if dircnt>dirlist.0 then DONE=YES
  3377.  
  3378.    do while ~DONE
  3379.       source=dirlist.dircnt                      /* directory to look thru*/
  3380.       call GetDirs                 /* Recursive Call to this same routine */ 
  3381.    end
  3382.  
  3383.    if show('L','rexxtricks.library') then do    /* use tricks library     */
  3384. say time() 'Using rexxtricks.library'
  3385.       call QSORT(dirlist)                       /* sort into pretty order */
  3386.    end
  3387.    else do                                      /* use QuickSort          */
  3388. say time() 'Using QuickSort'           
  3389.       call QSORT(1, dirlist.0, dirlist)         /* sort into pretty order */
  3390.    end
  3391.  
  3392. Return
  3393.  
  3394.  
  3395. /**************************************************************************/
  3396. /*                                                                        */
  3397. /*           Various routines called for debugging/trace options          */
  3398. /*                                                                        */
  3399. /**************************************************************************/
  3400. DumpArrays:
  3401.  
  3402.    if (DumpFiles | Debug) & Files.0 > 0 then call DumpFiles
  3403.    if (DumpPhase2 | Debug) & Files.0 > 0 then call DumpPhase2
  3404.    if (DumpMisc  | Debug) & Files.0 > 0 then call DumpMiscinfo
  3405.    if (DumpFroms | Debug) & Files.0 > 0 then call DumpFrominfo
  3406.    if (DumpSubjects | Debug) & Files.0 > 0 then call DumpSubjinfo
  3407.    if (DumpDates | Debug) & Files.0 > 0 then call DumpDateinfo 
  3408.    if (TrapAllBegs | Debug) & AllBegins.0 > 0 then call DumpBegins
  3409.    if (TrapAllEncs | Debug) & AllEncodes.0 > 0 then call DumpEncodes
  3410.    if (TrapAllSecs | Debug) & Allsections.0 > 0 then call DumpSections
  3411.  
  3412.                         /************************/
  3413.                         /*                      */
  3414.                         /* Dump these only once */
  3415.                         /*        at end        */
  3416.                         /************************/
  3417.  
  3418. if dirptr=dirlist.0 then do
  3419.    if (DumpBinTypes | Debug) & BinTypes.0 > 0 then call DumpBinTypes
  3420.    if (DumpBase64Types | Debug) & Base64Types.0 > 0 then call DumpBase64Types
  3421.    if (DumpEncTypes | Debug) & EncTypes.0 > 0 then call DumpEncTypes
  3422.    if (DumpSectionTypes | Debug) & SectionTypes.0 > 0 then call DumpSectionTypes
  3423.    if (DumpSkipFroms | Debug) & SkipFroms.0 > 0 then call DumpSkipFroms
  3424.    if (DumpSkipSubjects | Debug) & SkipSubjects.0 > 0 then call DumpSkipSubjects
  3425. end
  3426.  
  3427. Return
  3428.  
  3429. /**************************************************************************/
  3430. /*                                                                        */
  3431. /*              Dumps array used for directories on Recursive             */
  3432. /*                                                                        */
  3433. /**************************************************************************/
  3434. DumpDirs: 
  3435.  
  3436.    msg=' '
  3437.    interpret Saycmd
  3438.    if dirlist.0=1 then msg=dirlist.0 ' Directory found'
  3439.       else msg=dirlist.0 ' Directories found'
  3440.    interpret Saycmd
  3441.    msg=left(dashes,length(msg))
  3442.    interpret Saycmd
  3443.    do j=1 to dirlist.0                             /* dump dir list array */
  3444.       msg=dirlist.j
  3445.       interpret Saycmd
  3446.    end
  3447.    msg=' '
  3448.    interpret Saycmd
  3449.    
  3450. Return
  3451.  
  3452. /**************************************************************************/
  3453. /*                   Dumps Files. array for all partnames.                */
  3454. /**************************************************************************/
  3455. /*               (0)=cnt             (0)=cnt                              */
  3456. /* Files. format: filename.encodetype.partname.partnum.parttot.startline  */
  3457. /*                        .encodetype.partname.partnum.parttot.startline  */
  3458. /**************************************************************************/
  3459. DumpFiles:
  3460.  
  3461.    msg=' '
  3462.    interpret Saycmd
  3463.    msg='(DUMPFILES=YES)' Files.0 ' File(s)'
  3464.    interpret Saycmd
  3465.    msg='Format: Subject line'
  3466.    interpret saycmd
  3467.    msg='        Filename Encodetype Partname Partnum Parttot Startline ("."=missing)' 
  3468.    interpret saycmd
  3469.    msg=left(dashes,length(msg))
  3470.    interpret Saycmd
  3471.  
  3472.    do i=1 to Files.0   
  3473.       msg= Subjinfo.i.1.1
  3474.       interpret Saycmd
  3475.       msg=i Files.i.0 Files.i.1.0 Files.i.1.1.0 Files.i.1.1.1.0 Files.i.1.1.1.1.0
  3476.       interpret Saycmd
  3477.       if Files.i.1.0=0 then do
  3478.          msg=Files.i Files.i.1 Files.i.1.1 Files.i.1.1.1 Files.i.1.1.1.1 Files.i.1.1.1.1.1
  3479.          interpret Saycmd
  3480.       end
  3481.       else do 
  3482.          do j=1 to Files.i.1.0
  3483.          msg=Files.i Files.i.1 Files.i.1.j Files.i.1.j.1 Files.i.1.j.1.1 Files.i.1.j.1.1.1
  3484.          interpret Saycmd
  3485.          end
  3486.       end
  3487.       msg=' '
  3488.       interpret Saycmd
  3489.    end
  3490.  
  3491. Return
  3492.  
  3493. /**************************************************************************/
  3494. /*                   Dumps Partone. & Partxxx. arrays                     */
  3495. /**************************************************************************/
  3496. /*                                   (0)#partname matches in subject line */
  3497. /*                                         (0)#partnums in subject line   */
  3498. /*                                                    (0)#totals in sub   */
  3499. /*                   Files                  spart      spart              */
  3500. /* Partone.  format: Pointer.partname.sword.number.loc.total.loc.subjline */
  3501. /*                                                                        */
  3502. /* Partxxx.=same format as Partone.                                       */
  3503. /*                                                                        */
  3504. **************************************************************************/
  3505. DumpPhase2:
  3506.  
  3507.    msg=' '
  3508.    interpret Saycmd
  3509.    msg='(DUMPPHASE2=YES) Dumping Partone array:  ("."=missing)'
  3510.    interpret Saycmd
  3511.    msg='Format: Subject-line'
  3512.    interpret Saycmd
  3513.    msg='        Files                  spart      spart'  
  3514.    interpret saycmd
  3515.    msg='        Pointer partname sword number loc total loc'
  3516.    interpret Saycmd
  3517.    msg=left(dashes,length(msg))
  3518.    interpret Saycmd
  3519.    do j=1 to Partone.0
  3520.       msg=' '
  3521.       interpret Saycmd
  3522.       msg=Partone.j.1.1.1.1.1.1.1            /* subjline               */
  3523.       interpret Saycmd
  3524.       msg=Partone.j Partone.j.0 Partone.j.1.0 Partone.j.1.1.0 Partone.j.1.1.1.0 Partone.j.1.1.1.1.0 Partone.j.1.1.1.1.1.0 Partone.j.1.1.1.1.1.1.0
  3525.       interpret Saycmd
  3526.       if datatype(Partone.j.1.0,'N') & datatype(Partone.j.1.1.0,'N') & datatype(Partone.j.1.1.1.1.0,'N') then do
  3527.          kmax=max(Partone.j.1.0,Partone.j.1.1.0,Partone.j.1.1.1.1.0)  
  3528.       end
  3529.       else kmax=3                            /* assume max of 3        */
  3530.       do k=1 to kmax                         /* max depth of loops     */
  3531.          msg=Partone.j Partone.j.1
  3532.          msg=msg||' '||Partone.j.1.k
  3533.          msg=msg||' '||Partone.j.1.1.k
  3534.          msg=msg||' '||Partone.j.1.1.k.1
  3535.          msg=msg||' '||Partone.j.1.1.1.1.k
  3536.          msg=msg||' '||Partone.j.1.1.1.1.k.1
  3537.          interpret Saycmd
  3538.       end
  3539.    end
  3540.    msg=' '
  3541.    interpret Saycmd
  3542.    msg=' '
  3543.    interpret Saycmd
  3544.    msg='(DUMPPHASE2=YES) Dumping Partxxx array:  ("."=missing)'
  3545.    interpret Saycmd
  3546.    msg='Format: Subject-line'
  3547.    interpret Saycmd
  3548.    msg='        Files                  spart      spart'  
  3549.    interpret saycmd
  3550.    msg='        Pointer partname sword number loc total loc'
  3551.    interpret Saycmd
  3552.    msg=left(dashes,length(msg))
  3553.    interpret Saycmd
  3554.    do j=1 to Partxxx.0
  3555.       msg=' '
  3556.       interpret Saycmd
  3557.       msg=Partxxx.j.1.1.1.1.1.1.1            /* subjline               */
  3558.       interpret Saycmd
  3559.       msg=Partxxx.j Partxxx.j.0 Partxxx.j.1.0 Partxxx.j.1.1.0 Partxxx.j.1.1.1.0 Partxxx.j.1.1.1.1.0 Partxxx.j.1.1.1.1.1.0 Partxxx.j.1.1.1.1.1.1.0
  3560.       interpret Saycmd
  3561.       if datatype(Partxxx.j.1.0,'N') & datatype(Partxxx.j.1.1.0,'N') & datatype(Partxxx.j.1.1.1.1.0,'N') then do
  3562.          kmax=max(Partxxx.j.1.0,Partxxx.j.1.1.0,Partxxx.j.1.1.1.1.0)  
  3563.       end
  3564.       else kmax=3                            /* assume max of 3        */
  3565.       do k=1 to kmax                         /* max depth of loops     */
  3566.          msg=Partxxx.j Partxxx.j.1
  3567.          msg=msg||' '||Partxxx.j.1.k
  3568.          msg=msg||' '||Partxxx.j.1.1.k
  3569.          msg=msg||' '||Partxxx.j.1.1.k.1
  3570.          msg=msg||' '||Partxxx.j.1.1.1.1.k
  3571.          msg=msg||' '||Partxxx.j.1.1.1.1.k.1
  3572.          interpret Saycmd
  3573.       end
  3574.    end
  3575.    msg=' '
  3576.    interpret Saycmd
  3577.  
  3578. Return
  3579.  
  3580. /**************************************************************************/
  3581. /*                   Dumps Miscinfo array for all entries.                */
  3582. /**************************************************************************/
  3583. /* Miscinfo. format: filename.mimetype.decoded.filenoted.chopped.dupfile  */
  3584. /**************************************************************************/
  3585. DumpMiscInfo:
  3586.  
  3587.    msg=' '
  3588.    interpret Saycmd
  3589.    msg='(DUMPMISC=YES)' Files.0 ' File(s)'
  3590.    interpret Saycmd
  3591.    msg='format: FPtr Filename Mimetype Decoded Filenoted Chopped Dupfile ("."=missing)' 
  3592.    interpret saycmd
  3593.    msg=left(dashes,length(msg))
  3594.    interpret Saycmd
  3595.    do i=1 to Files.0   
  3596.       if Files.i.1.0=0 then do
  3597.          msg=i Files.i
  3598.          msg=msg||' '||Miscinfo.i.1 
  3599.          msg=msg||' '||Miscinfo.i.1.1
  3600.          msg=msg||' '||Miscinfo.i.1.1.1
  3601.          msg=msg||' '||Miscinfo.i.1.1.1.1
  3602.          msg=msg||' '||Miscinfo.i.1.1.1.1.1
  3603.          interpret Saycmd
  3604.       end
  3605.       else do 
  3606.          do j=1 to Files.i.1.0
  3607.             msg=i Files.i
  3608.             msg=msg||' '||Miscinfo.i.j 
  3609.             msg=msg||' '||Miscinfo.i.j.1
  3610.             msg=msg||' '||Miscinfo.i.j.1.1
  3611.             msg=msg||' '||Miscinfo.i.j.1.1.1
  3612.             msg=msg||' '||Miscinfo.i.j.1.1.1.1
  3613.             interpret Saycmd
  3614.          end
  3615.       end
  3616.       msg=' '
  3617.       interpret Saycmd
  3618.    end
  3619.  
  3620. Return
  3621.  
  3622. /**************************************************************************/
  3623. /*                                                                        */
  3624. /*                  Dumps array used for From lines                       */
  3625. /*                                                                        */
  3626. /**************************************************************************/
  3627. DumpFrominfo:
  3628.  
  3629.    msg=' '
  3630.    interpret Saycmd
  3631.    msg='(DUMPFROMS=YES)' 
  3632.    interpret Saycmd
  3633.    msg='Format: Filename SkipFlag DeleteFlag FromLine (0=No 1=Yes)'
  3634.    interpret saycmd
  3635.    msg=left(dashes,length(msg))
  3636.    interpret Saycmd
  3637.    do j=1 to Files.0                              /* dump Frominfo array */
  3638.       msg=Files.j '  ' Frominfo.j Frominfo.j.1 Frominfo.j.1.1
  3639.       interpret Saycmd
  3640.    end
  3641.    msg=' '
  3642.    interpret Saycmd
  3643.  
  3644. Return
  3645.  
  3646. /**************************************************************************/
  3647. /*                                                                        */
  3648. /*                  Dumps array used for Subject lines                    */
  3649. /*                                                                        */
  3650. /**************************************************************************/
  3651. DumpSubjinfo:
  3652.  
  3653.    msg=' '
  3654.    interpret Saycmd
  3655.    msg='(DUMPSUBJECTS=YES)' 
  3656.    interpret Saycmd
  3657.    msg='Format: Filename SkipFlag DeleteFlag SubjectLine (0=No 1=Yes)'
  3658.    interpret saycmd
  3659.    msg=left(dashes,length(msg))
  3660.    interpret Saycmd
  3661.    do j=1 to Files.0                              /* dump Subjinfo array */
  3662.       msg=Files.j '  ' Subjinfo.j Subjinfo.j.1 Subjinfo.j.1.1
  3663.       interpret Saycmd
  3664.    end
  3665.    msg=' '
  3666.    interpret Saycmd
  3667.  
  3668. Return
  3669.  
  3670. /**************************************************************************/
  3671. /*                                                                        */
  3672. /*                  Dumps array used for Date lines                       */
  3673. /*                                                                        */
  3674. /**************************************************************************/
  3675. DumpDateinfo:
  3676.  
  3677.    msg=' '
  3678.    interpret Saycmd
  3679.    msg='(DUMPDATES=YES)' 
  3680.    interpret Saycmd
  3681.    msg='Format: Filename SkipFlag DeleteFlag DateLine (0=No 1=Yes)'
  3682.    interpret saycmd
  3683.    msg=left(dashes,length(msg))
  3684.    interpret Saycmd
  3685.    do j=1 to Files.0                              /* dump Dateinfo array */
  3686.       msg=Files.j '  ' Dateinfo.j Dateinfo.j.1 Dateinfo.j.1.1
  3687.       interpret Saycmd
  3688.    end
  3689.    msg=' '
  3690.    interpret Saycmd
  3691.  
  3692. Return
  3693.  
  3694. /**************************************************************************/
  3695. /*                                                                        */
  3696. /*                  Dumps array used for determining BinTypes             */
  3697. /*                                                                        */
  3698. /**************************************************************************/
  3699. DumpBinTypes:
  3700.  
  3701.    msg=' '
  3702.    interpret Saycmd
  3703.    msg='(DUMPBINTYPES=YES)' 
  3704.    interpret Saycmd
  3705.    msg=BinTypes.0 ' binary types found in:' BinTypesFile
  3706.    interpret Saycmd
  3707.    msg=left(dashes,length(msg))
  3708.    interpret Saycmd
  3709.    do j=1 to BinTypes.0                          /* dump BinType array */
  3710.       msg=BinTypes.j
  3711.       interpret Saycmd
  3712.    end
  3713.    msg=' '
  3714.    interpret Saycmd
  3715.  
  3716. Return
  3717.  
  3718. /**************************************************************************/
  3719. /*                                                                        */
  3720. /*                  Dumps array used for determining EncTypes             */
  3721. /*                                                                        */
  3722. /**************************************************************************/
  3723. DumpEncTypes:
  3724.  
  3725.    msg=' '
  3726.    interpret Saycmd
  3727.    msg='(DUMPENCTYPES=YES)' 
  3728.    interpret Saycmd
  3729.    msg=EncTypes.0 ' Encode types found in:' EncTypesFile
  3730.    interpret Saycmd
  3731.    msg=left(dashes,length(msg))
  3732.    interpret Saycmd
  3733.    do j=1 to EncTypes.0                          /* dump Encode  array */
  3734.       msg=EncTypes.j EncTypes.j.1
  3735.       interpret Saycmd
  3736.    end
  3737.    msg=' '
  3738.    interpret Saycmd
  3739.  
  3740. Return
  3741.  
  3742. /**************************************************************************/
  3743. /*                                                                        */
  3744. /*               Dumps array used for determining Base64Types             */
  3745. /*                                                                        */
  3746. /**************************************************************************/
  3747. DumpBase64Types:
  3748.  
  3749.    msg=' '
  3750.    interpret Saycmd
  3751.    msg='(DUMPBASE64TYPES=YES)' 
  3752.    interpret Saycmd
  3753.    msg=Base64Types.0 ' Base64 types found in:' Base64TypesFile
  3754.    interpret Saycmd
  3755.    msg=left(dashes,length(msg))
  3756.    interpret Saycmd
  3757.    do j=1 to Base64Types.0                          /* dump Base64Type array */
  3758.       msg=Base64Types.j
  3759.       interpret Saycmd
  3760.    end
  3761.    msg=' '
  3762.    interpret Saycmd
  3763.  
  3764. Return
  3765.  
  3766. /**************************************************************************/
  3767. /*                                                                        */
  3768. /*                  Dumps array used for Section Line info                */
  3769. /*                                                                        */
  3770. /**************************************************************************/
  3771. DumpSectionTypes:
  3772.  
  3773.    msg=' '
  3774.    interpret Saycmd
  3775.    msg='(DUMPSECTIONTYPES=YES)' 
  3776.    interpret Saycmd
  3777.    msg=SectionTypes.0 ' section types found in:' SectionTypesFile
  3778.    interpret Saycmd
  3779.    msg=left(dashes,length(msg))
  3780.    interpret Saycmd
  3781.    do j=1 to SectionTypes.0                     /* dump SectionType array */
  3782.       msg=SectionTypes.j 
  3783.       do k=1 to SectionTypes.j
  3784.          msg=msg||' '||SectionTypes.j.k SectionTypes.j.k.k
  3785.       end
  3786.       msg=msg||' '||SectionTypes.j.1.1.1 SectionTypes.j.1.1.1.1 SectionTypes.j.1.1.1.1.1 SectionTypes.j.1.1.1.1.1.1
  3787.       interpret Saycmd
  3788.    end
  3789.    msg=' '
  3790.    interpret Saycmd
  3791.  
  3792. Return
  3793.  
  3794. /**************************************************************************/
  3795. /*                                                                        */
  3796. /*                Dumps array used for determining SkipFrom               */
  3797. /*                                                                        */
  3798. /**************************************************************************/
  3799. DumpSkipFroms:
  3800.  
  3801.    msg=' '
  3802.    interpret Saycmd
  3803.    msg='(DUMPSKIPFROMS=YES)' 
  3804.    interpret Saycmd
  3805.    msg=SkipFroms.0 ' userids in SkipFromFile:' SkipFromFile
  3806.    interpret Saycmd
  3807.    msg=left(dashes,length(msg))
  3808.    interpret Saycmd
  3809.    do j=1 to SkipFroms.0                          /* dump SkipFrom array */
  3810.       msg=SkipFroms.j
  3811.       interpret Saycmd
  3812.    end
  3813.    msg=' '
  3814.    interpret Saycmd
  3815.  
  3816. Return
  3817.  
  3818. /**************************************************************************/
  3819. /*                                                                        */
  3820. /*              Dumps array used for determining SkipSubject              */
  3821. /*                                                                        */
  3822. /**************************************************************************/
  3823. DumpSkipSubjects:
  3824.  
  3825.    msg=' '
  3826.    interpret Saycmd
  3827.    msg='(DUMPSKIPSUBJECTS=YES)' 
  3828.    interpret Saycmd
  3829.    msg=SkipSubjects.0 ' keys in SkipSubjectFile:' SkipSubjectFile
  3830.    interpret Saycmd
  3831.    msg=left(dashes,length(msg))
  3832.    interpret Saycmd
  3833.    do j=1 to SkipSubjects.0                    /* dump SkipSubject array */
  3834.       msg=SkipSubjects.j
  3835.       interpret Saycmd
  3836.    end
  3837.    msg=' '
  3838.    interpret Saycmd
  3839.  
  3840. Return
  3841.  
  3842. /**************************************************************************/
  3843. /*                                                                        */
  3844. /*                  Dumps array used for lines with 'BEGIN'               */
  3845. /*                                                                        */
  3846. /**************************************************************************/
  3847. DumpBegins:
  3848.  
  3849.    msg=' '
  3850.    interpret Saycmd
  3851.    msg='(TRAPALLBEGS=YES)' 
  3852.    interpret Saycmd
  3853.    msg='All lines with BEGIN in ' dirlist.dirptr
  3854.    interpret Saycmd
  3855.    msg=left(dashes,length(msg))
  3856.    interpret Saycmd
  3857.    do j=1 to AllBegins.0                          /* dump Allbegins array */
  3858.       msg=AllBegins.j
  3859.       interpret Saycmd
  3860.    end
  3861.    msg=' '
  3862.    interpret Saycmd
  3863.  
  3864. Return
  3865.  
  3866. /**************************************************************************/
  3867. /*                                                                        */
  3868. /*                  Dumps array used for lines with 'SECTION'             */
  3869. /*                                                                        */
  3870. /**************************************************************************/
  3871. DumpSections:
  3872.  
  3873.    msg=' '
  3874.    interpret Saycmd
  3875.    msg='(TRAPALLSECS=YES)' 
  3876.    interpret Saycmd
  3877.    msg='All lines with SECTION in ' dirlist.dirptr
  3878.    interpret Saycmd
  3879.    msg=left(dashes,length(msg))
  3880.    interpret Saycmd
  3881.    do j=1 to AllSections.0                         /* dump Frominfo array */
  3882.       msg=AllSections.j
  3883.       interpret Saycmd
  3884.    end
  3885.    msg=' '
  3886.    interpret Saycmd
  3887.  
  3888. Return
  3889.  
  3890. /**************************************************************************/
  3891. /*                                                                        */
  3892. /*                  Dumps array used for MIME encoding lines              */
  3893. /*                                                                        */
  3894. /**************************************************************************/
  3895. DumpEncodes: 
  3896.  
  3897.    msg=' '
  3898.    interpret Saycmd
  3899.    msg='(TRAPALLENCS=YES)' 
  3900.    interpret Saycmd
  3901.    msg='All MIME encoding Lines in ' dirlist.dirptr
  3902.    interpret Saycmd
  3903.    msg=left(dashes,length(msg))
  3904.    interpret Saycmd
  3905.    do j=1 to AllEncodes.0   
  3906.       msg=AllEncodes.j
  3907.       interpret Saycmd
  3908.    end
  3909.    msg=' '
  3910.    interpret Saycmd
  3911.  
  3912. Return
  3913.  
  3914. /**************************************************************************/
  3915. /*                                                                        */
  3916. /*                   Dump all runtime options to output                   */
  3917. /*                                                                        */
  3918. /**************************************************************************/
  3919. DumpOpts:
  3920.  
  3921.    msg=' '
  3922.    interpret Saycmd
  3923.    msg='(DUMPOPTS=YES)'
  3924.    interpret Saycmd
  3925.    msg='Using these runtime options: (0=NO,1=YES)'
  3926.    interpret Saycmd
  3927.    msg=left(dashes,length(msg))
  3928.    interpret Saycmd
  3929.    do i=1 to cmd.0
  3930.       tstr='tval='cmd.i
  3931.       interpret tstr
  3932.       msg='   '||cmd.i||'='||tval
  3933.       interpret Saycmd
  3934.    end 
  3935.  
  3936. Return
  3937.  
  3938.  
  3939. IOERR:
  3940.  
  3941.    SIGNAL OFF IOERR
  3942.    Say 'An I/O error has occurred - exiting'
  3943.    exit 20
  3944.  
  3945. SYNTAX:
  3946.  
  3947.    SIGNAL OFF SYNTAX
  3948.    Say 'An unexpected error has occurred - dumping values and exiting'
  3949.    Say 'Try to identify file with error and edit to fix'
  3950.    Say 'It is probably the LAST file in one of the arrays'
  3951.    Say ' '
  3952.    Say 'Line number with error' SIGL 'RC='RC  
  3953.    Say 'Line with error' sourceline(SIGL)  
  3954.    Say 'Current value of filename:' filename
  3955.    Say 'Current value of partname:' partname
  3956.    
  3957.    Say 'Dumping arrays ... '
  3958.    Call DumpDirs
  3959.    Call DumpFiles
  3960.    Call DumpPhase2
  3961.    Call DumpMiscInfo
  3962.    signal Cleanup
  3963.  
  3964. ===============  END OF ACTIVE CODE ================
  3965.